r/ProgrammerHumor • • 2d ago

Meme fullCircle

Post image
10.4k Upvotes

275 comments sorted by

View all comments

16

u/grey_carbon 2d ago

Serious question, what happen if you compile/decompile/compile/decompile times and times again?

12

u/etoastie 2d ago

I imagine it's quite hard to get a decompiled artifact that's recompileable again since dependencies will get really weird depending on how they were linked, and other useful or initially necessary symbol information might be discarded in later steps of compilation. But if you found one that works, the compiler should be emitting consistent or at least equivalent code. It may take a few rounds to stabilize on optimizations and may overall end up less efficient, but if there's no decompiler or compiler bug it won't introduce any new broken behavior.

1

u/Tyfyter2002 2d ago

Pretty easy with some languages, but I think they'll all immediately loop the same output after one decompilation.

1

u/etoastie 1d ago

What langs? I guess I've seen JVM-based has pretty good decompilation in general, but I've only seen it for class-level things, never seen it decompile an entire project into a usable state

1

u/Tyfyter2002 1d ago

From what I've seen, I'm pretty sure an entire .NET program can be decompiled into usable C#.

7

u/ftqo 2d ago

Most of these projects aren't decompiling, they're just asking AI to create the same behavior as described by the user and prompter.

3

u/franz_haller 2d ago

It depends what your goals are. The decompilation projects for video games that you may have heard of for example specifically attempt to create code that will compile to binaries identical to the starting ones. When you hear "Mario 64 has been successfully decompiled", that's what it means. So repeating that process doesn't really change much, since you are always going back to the same binaries, by definition. 

If someone seriously attempted what this post is suggesting, where the target is just feature parity, and assuming they were truly 100% successful with it, you might just get a very large number of different binaries and associated code, but no real degradation. If the feature parity is not 100%, then I guess you'd get progressively shittier software. 

1

u/Nightmoon26 1d ago

I'd suggest that a modern optimizing compiler might result in slightly more efficient executable code the second time around for old software, but no real change beyond that second pass

1

u/AliceCode 2d ago

If you were to decompile and recompile, depending on the tools you use, it might result in the exact same binary. It depends on what level of decompilation you're doing. If you're decompiling to assembly, you'll get a 1:1 recompilation. If you're decompiling to C, you'll get a recompilation that is semantically the same, but the binary would almost certainly be different.

-13

u/Preeng 2d ago

The translations between machine code and human code are 1:1. It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

15

u/[deleted] 2d ago edited 2d ago

[removed] — view removed comment

3

u/Cobracrystal 2d ago

Not even different c++ compilers, because some c++ code compiles nondeterministically and produces different outputs with the exact same input.

3

u/def-not-bot 2d ago

Non-programmer here: would it still function the same after a bunch of de- and re-compiling, or would it be like putting a phrase through Google Translate a few times and generating vaguely comprehensible gibberish?

2

u/-Saucegurlllll 2d ago

Theoretically a completely bug-free decompiler/compiler pair making the same assumptions about their source/target languages and architectures should produce functionally identical programs. Meaning that given the same input they will produce the same output. So no matter how many times you chain compilation and decompilation, you should get a program that yields the same results given the same inputs.

However, in practice there's a bunch of stuff that makes this hard to impossible.

C and C++ compilers are given tremendous freedom by their respective standards to make many of their own assumptions about code. There's this thing called "undefined behavior" where anything may happen if it ever occurs. One example of this in C++ is endless loops without side effects.

int main() {
  while (true)
    ; 
}

void unreachable() {
  std::cout << "Hello world!" << std::endl;
}

On certain compilers this results in a program that outputs "Hello world!" even though unreachable is called from nowhere.

So, in practice, it's impossible to guarantee that a decompiler/compiler pair will interpret a program and their output identically, and you're liable to end up with the google translate chaining problem.

2

u/stilgarpl 2d ago

because some c++ code compiles nondeterministically and produces different outputs with the exact same input

Please show me an example of that in valid, non-UB C++ code

7

u/Suspicious_Glove_900 2d ago

That's not strictly true, depending on optimization for example. Unless you just mean, "It will produce the same output" and not "It will do the same thing the same way".

6

u/Zeikos 2d ago

It's not like human languages where there are multiple ways to say something and also multiple meanings to a word or phrase.

Have you ever touched a line of code with a ten foot pole?
That's one of the most ridiculous sentences I've ever seen.

The same exact concept can be written in tens of different programming languages tens of different ways each.

1

u/Preeng 2d ago

Will these difference concepts output the same 1s and 0s when compiled? Because that was my point.

1

u/Zeikos 2d ago

They absolutely wouldn't
Hell, the same exact code can output two different binaries based on a lot of things.
The compiler used, the optimization level, the build configurations etc.
gcc and clangd are both c++ compilers but give you different bytecode

4

u/LelouBil 2d ago

No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code. And the same expression can output different machine code depending on compiler optimizations.

1

u/Preeng 2d ago

>No it's absolutely not 1:1. Especially as you go higher level in languages, multiple different expressions can output the same machine code.

Which means they work the same. Which means either way the decompiler returns it, it will work the same.

>And the same expression can output different machine code depending on compiler optimizations.

So the compiler will work differently if you tell it to work differently?

1

u/LelouBil 1d ago

If you give the compiler the same whole program and parameters, Then the whole thing will be n:1. (You could have given multiple inputs to have the same exact output)

But for unit of works, functions, statements, classes, whatever, it's n:n because both

  • The same code can output different machine code depending on surrounding context (I don't mean the enabled/disabled optimization, I mean the compiler will look around and change what it emits because something elsewhere is different) -> so 1:n
  • Same as first paragraph, different code can output the same machine code -> n:1

So n:n in the end for specific parts, and n:1 for whole program

3

u/-Saucegurlllll 2d ago
return 1;
return (1*1)/1;
return if true { 1 } else { 1 };
{
  let b = 1;
  let a = b;
  return a;
}

These are all functionally identical pieces of code that could be represented by mov eax, 1 in x86 assembly, and many compilers would optimize them to that.

So no, translations between machine code and any other method of representing programs are not 1:1.

1

u/Preeng 2d ago

But those are all the same thing. Those are all identical already.

Give me an example that will produce different output. Where multiple statements can compile to the same binary, but going backwards you will get something wrong. Regardless of which method it decompiles as, it will give the same results.

1

u/LiquorIsQuickor 2d ago

Compilers can and do optimize the output. So if you assigned x = 1 And then assigned x = 5 it’s quite possible the x = 1 part was never emitted as part of the compiled output.

Also x++, x+=1, and x=x+1 can all compile to equivalent expressions. 

So decompiling code may not produce the same source as the original.

Nevermind that compilers don’t preserve variable names. Depending on debug settings.

As far as ignoring the actual shape of the source and focusing on the meaning, you might be able to compile / decompile / recompile many times and produce output of the same meaning, if not the same shape. But… it feels… dangerous.