summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-objcopy/abs-symbol.test36
-rw-r--r--llvm/test/tools/llvm-objcopy/common-symbol.test84
-rw-r--r--llvm/test/tools/llvm-objcopy/section-index-unsupported.test15
-rw-r--r--llvm/tools/llvm-objcopy/Object.cpp58
-rw-r--r--llvm/tools/llvm-objcopy/Object.h20
5 files changed, 205 insertions, 8 deletions
diff --git a/llvm/test/tools/llvm-objcopy/abs-symbol.test b/llvm/test/tools/llvm-objcopy/abs-symbol.test
new file mode 100644
index 00000000000..fb261ce341a
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/abs-symbol.test
@@ -0,0 +1,36 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -symbols %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Symbols:
+ Global:
+ - Name: test
+ Index: SHN_ABS
+ Value: 0x1234
+
+#CHECK: Symbols [
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name:
+#CHECK-NEXT: Value: 0x0
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Local (0x0)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Undefined (0x0)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test
+#CHECK-NEXT: Value: 0x1234
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Absolute (0xFFF1)
+#CHECK-NEXT: }
+#CHECK-NEXT:]
diff --git a/llvm/test/tools/llvm-objcopy/common-symbol.test b/llvm/test/tools/llvm-objcopy/common-symbol.test
new file mode 100644
index 00000000000..919726d6598
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/common-symbol.test
@@ -0,0 +1,84 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -symbols %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Symbols:
+ Global:
+ - Name: test
+ Index: SHN_COMMON
+ Value: 0x1234
+ - Name: test2
+ Index: SHN_HEXAGON_SCOMMON
+ Value: 0x1235
+ - Name: test3
+ Index: SHN_HEXAGON_SCOMMON_2
+ Value: 0x1236
+ - Name: test4
+ Index: SHN_HEXAGON_SCOMMON_4
+ Value: 0x1237
+ - Name: test5
+ Index: SHN_HEXAGON_SCOMMON_8
+ Value: 0x1238
+
+#CHECK: Symbols [
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name:
+#CHECK-NEXT: Value: 0x0
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Local (0x0)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Undefined (0x0)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test
+#CHECK-NEXT: Value: 0x1234
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Common (0xFFF2)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test2
+#CHECK-NEXT: Value: 0x1235
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Processor Specific (0xFF00)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test3
+#CHECK-NEXT: Value: 0x1236
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Processor Specific (0xFF02)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test4
+#CHECK-NEXT: Value: 0x1237
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Processor Specific (0xFF03)
+#CHECK-NEXT: }
+#CHECK-NEXT: Symbol {
+#CHECK-NEXT: Name: test5
+#CHECK-NEXT: Value: 0x1238
+#CHECK-NEXT: Size: 0
+#CHECK-NEXT: Binding: Global (0x1)
+#CHECK-NEXT: Type: None (0x0)
+#CHECK-NEXT: Other: 0
+#CHECK-NEXT: Section: Processor Specific (0xFF04)
+#CHECK-NEXT: }
+#CHECK-NEXT:]
diff --git a/llvm/test/tools/llvm-objcopy/section-index-unsupported.test b/llvm/test/tools/llvm-objcopy/section-index-unsupported.test
new file mode 100644
index 00000000000..f2d32b6dd5e
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/section-index-unsupported.test
@@ -0,0 +1,15 @@
+# RUN: yaml2obj %s > %t
+# RUN: not llvm-objcopy %t %t2 2>&1 >/dev/null | FileCheck %s
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Symbols:
+ Global:
+ - Name: test
+ Index: 0xff05
+
+# CHECK: [[_:.*]] Symbol 'test' has unsupported value greater than or equal to SHN_LORESERVE: 65285
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