Index: test/tools/llvm-objcopy/keep-file-symbols.test =================================================================== --- test/tools/llvm-objcopy/keep-file-symbols.test +++ test/tools/llvm-objcopy/keep-file-symbols.test @@ -29,6 +29,15 @@ #STRIPALL: Symbols [ #STRIPALL-NEXT: Symbol { +#STRIPALL-NEXT: Name: +#STRIPALL-NEXT: Value: 0x0 +#STRIPALL-NEXT: Size: 0 +#STRIPALL-NEXT: Binding: Local +#STRIPALL-NEXT: Type: None +#STRIPALL-NEXT: Other: 0 +#STRIPALL-NEXT: Section: Undefined +#STRIPALL-NEXT: } +#STRIPALL-NEXT: Symbol { #STRIPALL-NEXT: Name: foo #STRIPALL-NEXT: Value: 0x0 #STRIPALL-NEXT: Size: 0 Index: test/tools/llvm-objcopy/strip-all-and-keep-symbol.test =================================================================== --- test/tools/llvm-objcopy/strip-all-and-keep-symbol.test +++ test/tools/llvm-objcopy/strip-all-and-keep-symbol.test @@ -58,6 +58,15 @@ #CHECK: Symbols [ #CHECK-NEXT: Symbol { +#CHECK-NEXT: Name: +#CHECK-NEXT: Value: 0x0 +#CHECK-NEXT: Size: 0 +#CHECK-NEXT: Binding: Local +#CHECK-NEXT: Type: None +#CHECK-NEXT: Other: 0 +#CHECK-NEXT: Section: Undefined +#CHECK-NEXT: } +#CHECK-NEXT: Symbol { #CHECK-NEXT: Name: foo #CHECK-NEXT: Value: 0x1000 #CHECK-NEXT: Size: 8 Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -116,7 +116,12 @@ void StringTableSection::finalize() { StrTabBuilder.finalize(); } void SectionWriter::visit(const StringTableSection &Sec) { - Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset); + uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + // We set the first byte of the string table to zero so that we ensure the + // zero symbol points to a '\0' character. + Buf[0] = 0; + + Sec.StrTabBuilder.write(Buf); } void StringTableSection::accept(SectionVisitor &Visitor) const { @@ -162,7 +167,7 @@ } void SymbolTableSection::assignIndices() { - uint32_t Index = 0; + uint32_t Index = 1; for (auto &Sym : Symbols) Sym->Index = Index++; } @@ -251,6 +256,12 @@ } const Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) const { + // As we count the zero symbol for indexes, we need to handle correctly here + if (Index == 0) + error("Null symbol might not be accessed"); + + --Index; + if (Symbols.size() <= Index) error("Invalid symbol index: " + Twine(Index)); return Symbols[Index].get(); @@ -266,6 +277,17 @@ uint8_t *Buf = Out.getBufferStart(); Buf += Sec.Offset; typename ELFT::Sym *Sym = reinterpret_cast(Buf); + // We need to write the null symbol separately, as we are not exposing it + // in the SymbolTableSection. + Sym->st_name = 0; + Sym->st_value = 0; + Sym->st_size = 0; + Sym->st_other = 0; + Sym->setBinding(STB_LOCAL); + Sym->setType(STT_NOTYPE); + Sym->st_shndx = 0; + ++Sym; + // Loop though symbols setting each entry of the symbol table. for (auto &Symbol : Sec.Symbols) { Sym->st_name = Symbol->NameIndex; @@ -332,7 +354,8 @@ for (const auto &Reloc : Relocations) { Buf->r_offset = Reloc.Offset; setAddend(*Buf, Reloc.Addend); - Buf->setSymbolAndType(Reloc.RelocSymbol->Index, Reloc.Type, false); + Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0, + Reloc.Type, false); ++Buf; } } @@ -624,7 +647,12 @@ const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); + uint32_t Index = 0; for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) { + if (Index == 0) { + ++Index; + continue; + } SectionBase *DefSection = nullptr; StringRef Name = unwrapOrError(Sym.getName(StrTabData)); @@ -663,7 +691,9 @@ ToAdd.Offset = Rel.r_offset; getAddend(ToAdd.Addend, Rel); ToAdd.Type = Rel.getType(false); - ToAdd.RelocSymbol = SymbolTable->getSymbolByIndex(Rel.getSymbol(false)); + uint32_t SymIndex = Rel.getSymbol(false); + ToAdd.RelocSymbol = + SymIndex ? SymbolTable->getSymbolByIndex(SymIndex) : nullptr; Relocs->addRelocation(ToAdd); } } @@ -1105,6 +1135,12 @@ Obj.SymbolTable->addSymbolNames(); Obj.sortSections(); + + // If there is a SymbolTable, we need to add the null symbol entry to the + // section's total size, so that assignOffsets() can compute offsets correctly + if (Obj.SymbolTable) + Obj.SymbolTable->Size += Obj.SymbolTable->EntrySize; + assignOffsets(); // Finalize SectionNames first so that we can assign name indexes. Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -292,9 +292,7 @@ return true; } - // TODO: We might handle the 'null symbol' in a different way - // by probably handling it the same way as we handle 'null section' ? - if (Config.StripUnneeded && !Sym.Referenced && Sym.Index != 0 && + if (Config.StripUnneeded && !Sym.Referenced && (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) && Sym.Type != STT_FILE && Sym.Type != STT_SECTION) return true;