summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objcopy')
-rw-r--r--llvm/tools/llvm-objcopy/Object.cpp58
-rw-r--r--llvm/tools/llvm-objcopy/Object.h20
2 files changed, 70 insertions, 8 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp
index 365e9ada12f..cad97b93c3f 100644
--- a/llvm/tools/llvm-objcopy/Object.cpp
+++ b/llvm/tools/llvm-objcopy/Object.cpp
@@ -90,14 +90,54 @@ void StringTableSection::writeSection(FileOutputBuffer &Out) const {
StrTabBuilder.write(Out.getBufferStart() + Offset);
}
+static bool isValidReservedSectionIndex(uint16_t Index) {
+ switch (Index) {
+ case SHN_ABS:
+ case SHN_COMMON:
+ case SHN_HEXAGON_SCOMMON:
+ case SHN_HEXAGON_SCOMMON_2:
+ case SHN_HEXAGON_SCOMMON_4:
+ case SHN_HEXAGON_SCOMMON_8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+uint16_t Symbol::getShndx() const {
+ if (DefinedIn != nullptr) {
+ return DefinedIn->Index;
+ }
+ switch (ShndxType) {
+ // This means that we don't have a defined section but we do need to
+ // output a legitimate section index.
+ case SYMBOL_SIMPLE_INDEX:
+ return SHN_UNDEF;
+ case SYMBOL_ABS:
+ case SYMBOL_COMMON:
+ case SYMBOL_HEXAGON_SCOMMON:
+ case SYMBOL_HEXAGON_SCOMMON_2:
+ case SYMBOL_HEXAGON_SCOMMON_4:
+ case SYMBOL_HEXAGON_SCOMMON_8:
+ return static_cast<uint16_t>(ShndxType);
+ }
+ llvm_unreachable("Symbol with invalid ShndxType encountered");
+}
+
void SymbolTableSection::addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,
SectionBase *DefinedIn, uint64_t Value,
- uint64_t Sz) {
+ uint16_t Shndx, uint64_t Sz) {
Symbol Sym;
Sym.Name = Name;
Sym.Binding = Bind;
Sym.Type = Type;
Sym.DefinedIn = DefinedIn;
+ if (DefinedIn == nullptr) {
+ if (isValidReservedSectionIndex(Shndx))
+ Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
+ else
+ Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
+ }
Sym.Value = Value;
Sym.Size = Sz;
Sym.Index = Symbols.size();
@@ -146,10 +186,7 @@ void SymbolTableSectionImpl<ELFT>::writeSection(
Sym->st_size = Symbol->Size;
Sym->setBinding(Symbol->Binding);
Sym->setType(Symbol->Type);
- if (Symbol->DefinedIn)
- Sym->st_shndx = Symbol->DefinedIn->Index;
- else
- Sym->st_shndx = SHN_UNDEF;
+ Sym->st_shndx = Symbol->getShndx();
++Sym;
}
}
@@ -251,7 +288,14 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {
SectionBase *DefSection = nullptr;
StringRef Name = unwrapOrError(Sym.getName(StrTabData));
- if (Sym.st_shndx != SHN_UNDEF) {
+ if (Sym.st_shndx >= SHN_LORESERVE) {
+ if (!isValidReservedSectionIndex(Sym.st_shndx)) {
+ error(
+ "Symbol '" + Name +
+ "' has unsupported value greater than or equal to SHN_LORESERVE: " +
+ Twine(Sym.st_shndx));
+ }
+ } else if (Sym.st_shndx != SHN_UNDEF) {
if (Sym.st_shndx >= Sections.size())
error("Symbol '" + Name +
"' is defined in invalid section with index " +
@@ -259,7 +303,7 @@ void Object<ELFT>::initSymbolTable(const llvm::object::ELFFile<ELFT> &ElfFile,
DefSection = Sections[Sym.st_shndx - 1].get();
}
SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection,
- Sym.getValue(), Sym.st_size);
+ Sym.getValue(), Sym.st_shndx, Sym.st_size);
}
}
diff --git a/llvm/tools/llvm-objcopy/Object.h b/llvm/tools/llvm-objcopy/Object.h
index 61d5f80c051..dff3fc40893 100644
--- a/llvm/tools/llvm-objcopy/Object.h
+++ b/llvm/tools/llvm-objcopy/Object.h
@@ -113,15 +113,32 @@ public:
}
};
+// Symbols have a st_shndx field that normally stores an index but occasionally
+// stores a different special value. This enum keeps track of what the st_shndx
+// field means. Most of the values are just copies of the special SHN_* values.
+// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
+enum SymbolShndxType {
+ SYMBOL_SIMPLE_INDEX = 0,
+ SYMBOL_ABS = llvm::ELF::SHN_ABS,
+ SYMBOL_COMMON = llvm::ELF::SHN_COMMON,
+ SYMBOL_HEXAGON_SCOMMON = llvm::ELF::SHN_HEXAGON_SCOMMON,
+ SYMBOL_HEXAGON_SCOMMON_2 = llvm::ELF::SHN_HEXAGON_SCOMMON_2,
+ SYMBOL_HEXAGON_SCOMMON_4 = llvm::ELF::SHN_HEXAGON_SCOMMON_4,
+ SYMBOL_HEXAGON_SCOMMON_8 = llvm::ELF::SHN_HEXAGON_SCOMMON_8,
+};
+
struct Symbol {
uint8_t Binding;
SectionBase *DefinedIn;
+ SymbolShndxType ShndxType;
uint32_t Index;
llvm::StringRef Name;
uint32_t NameIndex;
uint64_t Size;
uint8_t Type;
uint64_t Value;
+
+ uint16_t getShndx() const;
};
class SymbolTableSection : public SectionBase {
@@ -132,7 +149,8 @@ protected:
public:
void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
void addSymbol(llvm::StringRef Name, uint8_t Bind, uint8_t Type,
- SectionBase *DefinedIn, uint64_t Value, uint64_t Sz);
+ SectionBase *DefinedIn, uint64_t Value, uint16_t Shndx,
+ uint64_t Sz);
void addSymbolNames();
const Symbol *getSymbolByIndex(uint32_t Index) const;
void finalize() override;
OpenPOWER on IntegriCloud