-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
Problem:
I'm trying to insert some data into my ELF file. To achieve this, I create a const char array with the attribute __attribute__((section(".rodata.holder"))). Then, I try to insert the data into the object file using llvm-objcopy --update-section. However, during the linking process, I get an error from the linker:
ld.lld: error: found an extended symbol index (5), but unable to locate the extended symbol index table
How to reproduce:
Step 1 : Download and build llvm 21.1.5 tools
git clone https://github.com/llvm/llvm-project.git && cd llvm-project && git checkout llvmorg-21.1.5
mkdir bld && cd bld
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_ENABLE_PROJECTS="llvm;clang;lld" ../llvm
ninja clang lld llvm-objcopyStep 2 : Put broken sources into build directory
Source examples:
// main.cpp
int External(const char*, const char*, const char*) { return 0; }
int main() { return 0; }//lib.cpp
static __attribute__((section(".rodata.holder"))) const char resource_holder[0x1000] = {0};
int External(const char*, const char*, const char*);
static const int REG1 = External("Range1", resource_holder + 128 * 0, resource_holder + 128 * 1);
static const int REG2 = External("Range2", resource_holder + 128 * 1, resource_holder + 128 * 2);
static const int REG3 = External("Range3", resource_holder + 128 * 2, resource_holder + 128 * 3);Generate some random binary data:
head -c 4k /dev/urandom > data.binStep 3 : Try to compile
./bin/clang++ lib.cpp -c -O0 -g0 -o lib.o
./bin/llvm-objcopy lib.o --update-section=.rodata.holder=data.bin
./bin/clang++ lib.o main.cpp -o a.out -fuse-ld=lld --ld-path=./bin/ld.lld
# ld.lld: error: found an extended symbol index (5), but unable to locate the extended symbol index table
Possible bug(?) explanation
I've spent some time debugging. It seems the problem is related to the code of the Object::updateSectionData function:
llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.cpp
Lines 2160 to 2182 in 3b83e7f
| Error Object::updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data) { | |
| if (!Sec->hasContents()) | |
| return createStringError( | |
| errc::invalid_argument, | |
| "section '%s' cannot be updated because it does not have contents", | |
| Sec->Name.c_str()); | |
| if (Data.size() > Sec->Size && Sec->ParentSegment) | |
| return createStringError(errc::invalid_argument, | |
| "cannot fit data of size %zu into section '%s' " | |
| "with size %" PRIu64 " that is part of a segment", | |
| Data.size(), Sec->Name.c_str(), Sec->Size); | |
| if (!Sec->ParentSegment) { | |
| Sec = std::make_unique<OwnedDataSection>(*Sec, Data); | |
| } else { | |
| // The segment writer will be in charge of updating these contents. | |
| Sec->Size = Data.size(); | |
| UpdatedSections[Sec.get()] = Data; | |
| } | |
| return Error::success(); | |
| } |
If we create a new section, then there will not be any calls to Object::replaceSections:
llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.cpp
Lines 2173 to 2179 in 3b83e7f
| if (!Sec->ParentSegment) { | |
| Sec = std::make_unique<OwnedDataSection>(*Sec, Data); | |
| } else { | |
| // The segment writer will be in charge of updating these contents. | |
| Sec->Size = Data.size(); | |
| UpdatedSections[Sec.get()] = Data; | |
| } |
So, the symbols were not updated with the appropriate section index and an error occurred.
Could anyone tell me is it correct behaviour or we should fix it?