I feel like this is the kind of thing that could explode if the compiler/linker decide to get creative with how the functions are laid out in the binary, to improve locality and whatnot.
To inject a DLL into another process, you need some bootstrapping code so that you can a) have some entry point to create a new thread in that process, and b) do any initialization required by that DLL.
It's naughty because the language provides no guarantees about the memory layout of functions. There's no guarantee that the entirety of foo() will be between &foo and &bar, or that &bar > &foo. Actually, I had to tweak the compiler settings because it kept inserting a stack guard that pointed to an address outside the function.
I wonder if there's a setting to force the compiler to lay out the instruction memory in the contiguous way you're using it.
That sure would be cool. Without such guarantees the only way to write the above properly would be to analyze the generated code by disassembling it so that you can find all the possible bits that belong to that function. And obviously if the compiler has the great idea to do jmp eax anywhere, the problem becomes much, much harder.
Honestly, though, you usually don’t need to worry too much about the exact size of your functions when injecting a process. The size of the functions is often much smaller than the available data space being injected...
That said, this is something that is not uncommon in low-level C programming to determine the size of a function. Just mind your compiler’s default optimizations. (IIRC, both GCC and MSVC need no adjustment by default.)
Linker: https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_19.html
Something like this, but you may need to tweak things.
Put all the functions marked as copycode together in one linker section, and define a couple of symbols (which you can then extern from your source code) to tell you how much to copy.