CTSRD-CHERI / clang

DO NOT USE. Use llvm-project instead
Other
9 stars 8 forks source link

clang not resolving static assignments correctly in shared libraries #102

Closed brooksdavis closed 6 years ago

brooksdavis commented 8 years ago

When compiling libc/local/table.c, we have an initializer for _DefaultRuneLocale

const _RuneLocale _DefaultRuneLocale = {
...
};

followed

#undef _CurrentRuneLocale
const _RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;

Despite them being in the same translation unit, the capreloc entry for _CurrentRuneLocale ends up being:

entry: 0
        capability location: 0x11c50
        object: 0
        offset: 0
        size: 0
        permissions: 0

In libc, capsizefix further compounds the problem by deciding that the size of objects with address 0 have a size of 0x80. For simple testing, the following Makefile installed in a subdirectory of src/lib compiles locale/table.c by it self. An up to date tree is required to build a shared library.

.PATH: ${.CURDIR}/../libc/locale

LIB=    localetable
SRCS=   table.c
CFLAGS= -I${.CURDIR}/../libc/locale

WARNS?= 2

WANT_DUMP=yes

.include <bsd.lib.mk>
davidchisnall commented 8 years ago

I presume that this is because the address of _DefaultRuneLocale is not known statically and capsizefix doesn't know about dynamic relocations. If we had a proper linker, then the address would be 0 and there would be a dynamic relocation for the symbol. We probably need to do something similar, but I'm not sure how much it's worth continuing to pile hacks into capsizefix vs starting to emit proper dynamic relocs.

davidchisnall commented 8 years ago

Note: Not using -cheri-linker for dynamic binaries will probably fix this, as we'll then end up with the initialisers being generated as executable code.

davidchisnall commented 8 years ago

It might also be fairly simple to have capsizefix look at dynamic relocs and ignore any entries that have address 0 and dynamic relocs applied. We would still need rtld to do the same thing as capsizefix for addresses that had dynamic relocs.

brooksdavis commented 8 years ago

_DefaultRuneLocale is defined and initialized in this in this translation unit. Having capsizefix ignore unresolved dynamic objects probably does make sense.

davidchisnall commented 8 years ago

It doesn't matter that it's defined in this compilation unit. The address of the global, in a PIC translation unit, is not known until compile time. In code, it doesn't matter because its offset from the code is known at (static) link time and so you can do a PC-relative static relocation and then a PC-relative load, but that's not the case here: we need to generate a capability that has an address that isn't known until load time. In a normal dynamically linked application, this will be handled by a dynamic relocation, but we don't currently have dynamic relocations for capabilities.

davidchisnall commented 8 years ago

Note that capsizefix can't easily emit relocations here either: it is doing in-place modification of the binary and doing this properly would require doing something more like a linker and emitting a new modified binary with larger reloc sections.

brooksdavis commented 6 years ago

This is OBE and cap-table will should finish the job.