That's... complicated to answer.
My analyzers rely on an accurate Ghidra database, at least for the parts you want to export. While I've put a fair amount of effort into logging the various issues than can crop up which require fixing, they can't see what isn't there. In particular, missing references and truncation of variables won't be detected and will result in exotic undefined behavior.
There are ways to track down some of these issues. The best I've found so far is to relink the executable at a different base address and making sure that the original program's address ranges are unmapped ; that should lead to segmentation faults when absolute relocation spots are missed that can be debugged (but that only works if your target has a MMU). Truncated variables are very tricky to troubleshoot (especially if you don't suspect it) since it's the memory following the truncated variable that gets corrupted. An integer that is mistaken for a pointer can also be very tricky to track down, as the integer's value will vary depending on the address the target symbol gets, leading to erratic program behavior (that's especially an issue for a program loaded very low in the address space).
That being said, if the Ghidra database is accurate enough and you export back to the same object file format used originally and you subsequently use it onto the same platform with the same toolchain, you can delink megabytes of program code and data successfully. I consider that if the linker did it, then it should be possible to undo it.
Now, if you start cross-delinking to something that doesn't match the original program's platform and toolchain (like delinking from a Linux i386 ELF executable into a COFF object file and using it with a i386 Windows toolchain) then it's another story. If the exporter can express the relocations then you might end up with a working relocatable object file, but you'll still have potentially mismatched ABIs to contend with. It can be done, but that's not something I would recommend as a first project.
TL;DR Depending on what you do and the accuracy of the Ghidra database, it can range from "it just works" all the way to praying to Cthulhu for mercy.
int getSpecialArrayElement(char *array, uint64 key) {
i = computeOffset(key);
return array[i];
}
Compute offset can be arbitrarily complex (and probably deliberately hard to analyze if obfuscation is desired). There's nothing that prevents this function from accessing arbitrary locations in memory. You don't know if this will be accessing symbols that are already defined in memory by the linker short of exhaustively trying all possible inputs (and computeOffset may have turing traps for that).Assuming it doesn't reference any other global data and only contains relative jumps and branches, computeOffset() won't have any mandatory relocation spots [1] and therefore can be put into an object file as-is. Similarly, getSpecialArrayElement() would only have a relocation for the address of computeOffset() because array is supplied as a parameter, not as a global variable. Furthermore, any data allocated on the heap is transparent during delinking.
From my experience, "normal" everyday programs written in high-level languages typically don't contain nasty surprises while trying to delink them. That is not to say that obfuscated programs won't cause problems, but I haven't attempted delinking one so far [2].
[1] PC-relative relocations can be trimmed if the source and target are part of the same continuous address range being exported, because in that case the value won't change.
[2] I do have a pet peeve against developers who cast raw integer constants as pointers on MIPS, because the code sequence may be different than what the HI16/LO16 relocation pattern can tolerate and it requires binary patching to fix up (LUI/ADDIU versus LUI/ORI). If the integer was a multiple of 65536, is passed directly as a parameter to a function call and the compiler elided the second instruction then it can't be fixed in place and must be worked around some way, if the original value can't be kept (like the address for the scratchpad on the PlayStation for example, as long as you stay on that platform or can map memory there).