[lld] ELF needs type for SharedLibraryAtom.

The following code currently links incorrectly when linking against a dynamic libc on Ubuntu 12.10 unless -fpic is specified.

#include <stdio.h>

int main() {
fputs(“hi\n”, stdout);
}

The reason is that stdout gets a R_X86_64_PC32 relocation, but is of type Object. The ELF writer can’t see this, and assumes all R_X86_64_PC32 relocations in dynamic outputs are to functions and thus need PLT entries. The correct behavior is to treat this as a R_X86_64_GOTPCREL relocation. As this is what both gnu-ld and gold do.

To handle this correctly we will need to add type information to SharedLibraryAtom. We will also need to know about STT_COMMON in the future.

  • Michael Spencer

Mach-o uses different relocations (X86_64_RELOC_BRANCH and X86_64_RELOC_SIGNED) to differentiate the two.

I don’t think we need to copy the full ContentType from DefinedAtom. We just need to know if the DSO symbol is code or data.

Also the mach-o linker will need to know if a SharedLibraryAtom is a weak-definition or not.

-Nick

The following code currently links incorrectly when linking against a dynamic libc on Ubuntu 12.10 unless -fpic is specified.

#include <stdio.h>

int main() {
   fputs("hi\n", stdout);
}

The reason is that stdout gets a R_X86_64_PC32 relocation, but is of type Object. The ELF writer can't see this, and assumes all R_X86_64_PC32 relocations in dynamic outputs are to functions and thus need PLT entries. The correct behavior is to treat this as a R_X86_64_GOTPCREL relocation. As this is what both gnu-ld and gold do.

To handle this correctly we will need to add type information to SharedLibraryAtom. We will also need to know about STT_COMMON in the future.

Mach-o uses different relocations (X86_64_RELOC_BRANCH and X86_64_RELOC_SIGNED) to differentiate the two.

I don’t think we need to copy the full ContentType from DefinedAtom. We just need to know if the DSO symbol is code or data.

Since we are at it, we should add a type for undefinedAtoms too, not sure what to call it.

This is needed for TLS. A undefined symbol could be set to TLS, so that symbols are resolved with the same type.

Also the mach-o linker will need to know if a SharedLibraryAtom is a weak-definition or not.

The SharedLibraryAtoms have a field canBeNullAtRuntime, could this be used for weak definitions ?

Thanks

Shankar Easwaran

Isn't this the missing-copy-relocation item?

Joerg

Also the shared library atoms would need to have content(for data symbols), for the issue that Joerg brought. With GNU linkers, any external data reference from the executable thats resolved from a shared library, is copied into the main executable.

Not sure why this is being done for a long time with the GNU linker.

Thanks

Shankar Easwaran

Because the main program is not PIC, it will only use absolute
references to global symbols. For functions, you can create a PLT
record, but for data access, you have to hide the real symbol and copy
the content over to the equivalent in the main binary.

Joerg

The following code currently links incorrectly when linking against a dynamic libc on Ubuntu 12.10 unless -fpic is specified.

#include <stdio.h>

int main() {
  fputs("hi\n", stdout);
}

The reason is that stdout gets a R_X86_64_PC32 relocation, but is of type Object. The ELF writer can't see this, and assumes all R_X86_64_PC32 relocations in dynamic outputs are to functions and thus need PLT entries. The correct behavior is to treat this as a R_X86_64_GOTPCREL relocation. As this is what both gnu-ld and gold do.

To handle this correctly we will need to add type information to SharedLibraryAtom. We will also need to know about STT_COMMON in the future.

Mach-o uses different relocations (X86_64_RELOC_BRANCH and X86_64_RELOC_SIGNED) to differentiate the two.

I don’t think we need to copy the full ContentType from DefinedAtom. We just need to know if the DSO symbol is code or data.

Since we are at it, we should add a type for undefinedAtoms too, not sure what to call it.

This is needed for TLS. A undefined symbol could be set to TLS, so that symbols are resolved with the same type.

Yes.

Also the mach-o linker will need to know if a SharedLibraryAtom is a weak-definition or not.

The SharedLibraryAtoms have a field canBeNullAtRuntime, could this be used for weak definitions ?

I think you are confusing the two overloaded uses of "weak". canBeNullAtRuntime is for "weak imports" (can be missing at runtime). "Weak definitions" are used with C++ (can be multiple at runtime). For instance operator new in libc++.dylib is a weak definition. A program which defines its own (non-weak) operator new, will override the one in libc++.dylib.

-Nick

Hi Nick,

The SharedLibraryAtoms have a field canBeNullAtRuntime, could this be used for weak definitions ?

I think you are confusing the two overloaded uses of "weak". canBeNullAtRuntime is for "weak imports" (can be missing at runtime). "Weak definitions" are used with C++ (can be multiple at runtime). For instance operator new in libc++.dylib is a weak definition. A program which defines its own (non-weak) operator new, will override the one in libc++.dylib.

Thanks for making it clear. Agree completely. ELF also would need the same info.

ELF also needs content of the atom, unfortunately for Shared Library data atoms.

Shankar Easwaran

On Darwin, non-PIC programs use runtime text-relocations. The loader modifies the instructions (which are referencing absolute addresses) to reference the right runtime address (in some shared library).

How can copying data work? If a program references data in a shared library, and you copy the data into the program, you now have two copies of the data and their content can diverge.

Is this "missing-copy-relocation" a build time or runtime relocation? That is, does the static linker copy the data content? or the runtime loader (ld.so)?

-Nick

Not sure why this is being done for a long time with the GNU linker.

Because the main program is not PIC, it will only use absolute
references to global symbols. For functions, you can create a PLT
record, but for data access, you have to hide the real symbol and copy
the content over to the equivalent in the main binary.

On Darwin, non-PIC programs use runtime text-relocations. The loader modifies the instructions (which are referencing absolute addresses) to reference the right runtime address (in some shared library).

How can copying data work? If a program references data in a shared library, and you copy the data into the program, you now have two copies of the data and their content can diverge.

Yes it does get a copy of the data in the main program. What the main program does is it exports its definition so that the runtime resolver will resolve against the copied data. So essentially at runtime even if you have two copies of the data, the dynamic library still refers to the program's copy.

Is this "missing-copy-relocation" a build time or runtime relocation? That is, does the static linker copy the data content? or the runtime loader (ld.so)?

Few ELF linkers perform the optimization at static linktime to avoid runtime copies. The GNU linker by default just reserves the size in the bss section and the runtime linker copies the data.

So the runtime relocation would have R_*_GLOB_DAT instead of R_*_COPY.

Thanks

Shankar Easwaran