summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/COFF/Writer.cpp
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2019-01-19 19:42:35 +0000
committerMartin Storsjo <martin@martin.st>2019-01-19 19:42:35 +0000
commitf9e1434ef43e96dcb868d68fa1166a3a0531caa6 (patch)
tree1ba6f431da111afa6c3c642f026d431c56ce1e8f /llvm/tools/llvm-objcopy/COFF/Writer.cpp
parente9f62f62ce436067f3ae2be479f04bfc9ba8b53b (diff)
downloadbcm5719-llvm-f9e1434ef43e96dcb868d68fa1166a3a0531caa6.tar.gz
bcm5719-llvm-f9e1434ef43e96dcb868d68fa1166a3a0531caa6.zip
[llvm-objcopy] [COFF] Add support for removing sections
Differential Revision: https://reviews.llvm.org/D56683 llvm-svn: 351660
Diffstat (limited to 'llvm/tools/llvm-objcopy/COFF/Writer.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Writer.cpp68
1 files changed, 55 insertions, 13 deletions
diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
index c347810dd24..9fb7812672b 100644
--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
@@ -25,7 +25,7 @@ using namespace object;
using namespace COFF;
Error COFFWriter::finalizeRelocTargets() {
- for (Section &Sec : Obj.Sections) {
+ for (Section &Sec : Obj.getMutableSections()) {
for (Relocation &R : Sec.Relocs) {
const Symbol *Sym = Obj.findSymbol(R.Target);
if (Sym == nullptr)
@@ -39,8 +39,48 @@ Error COFFWriter::finalizeRelocTargets() {
return Error::success();
}
+Error COFFWriter::finalizeSectionNumbers() {
+ for (Symbol &Sym : Obj.getMutableSymbols()) {
+ if (Sym.TargetSectionId <= 0) {
+ // Undefined, or a special kind of symbol. These negative values
+ // are stored in the SectionNumber field which is unsigned.
+ Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId);
+ } else {
+ const Section *Sec = Obj.findSection(Sym.TargetSectionId);
+ if (Sec == nullptr)
+ return make_error<StringError>("Symbol " + Sym.Name +
+ " points to a removed section",
+ object_error::invalid_symbol_index);
+ Sym.Sym.SectionNumber = Sec->Index;
+
+ if (Sym.Sym.NumberOfAuxSymbols == 1 &&
+ Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) {
+ coff_aux_section_definition *SD =
+ reinterpret_cast<coff_aux_section_definition *>(Sym.AuxData.data());
+ uint32_t SDSectionNumber;
+ if (Sym.AssociativeComdatTargetSectionId == 0) {
+ // Not a comdat associative section; just set the Number field to
+ // the number of the section itself.
+ SDSectionNumber = Sec->Index;
+ } else {
+ Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId);
+ if (Sec == nullptr)
+ return make_error<StringError>(
+ "Symbol " + Sym.Name + " is associative to a removed section",
+ object_error::invalid_symbol_index);
+ SDSectionNumber = Sec->Index;
+ }
+ // Update the section definition with the new section number.
+ SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber);
+ SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16);
+ }
+ }
+ }
+ return Error::success();
+}
+
void COFFWriter::layoutSections() {
- for (auto &S : Obj.Sections) {
+ for (auto &S : Obj.getMutableSections()) {
if (S.Header.SizeOfRawData > 0)
S.Header.PointerToRawData = FileSize;
FileSize += S.Header.SizeOfRawData; // For executables, this is already
@@ -57,7 +97,7 @@ void COFFWriter::layoutSections() {
}
size_t COFFWriter::finalizeStringTable() {
- for (auto &S : Obj.Sections)
+ for (const auto &S : Obj.getSections())
if (S.Name.size() > COFF::NameSize)
StrTabBuilder.add(S.Name);
@@ -67,7 +107,7 @@ size_t COFFWriter::finalizeStringTable() {
StrTabBuilder.finalize();
- for (auto &S : Obj.Sections) {
+ for (auto &S : Obj.getMutableSections()) {
if (S.Name.size() > COFF::NameSize) {
snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d",
(int)StrTabBuilder.getOffset(S.Name));
@@ -97,6 +137,8 @@ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
Error COFFWriter::finalize(bool IsBigObj) {
if (Error E = finalizeRelocTargets())
return E;
+ if (Error E = finalizeSectionNumbers())
+ return E;
size_t SizeOfHeaders = 0;
FileAlignment = 1;
@@ -113,10 +155,10 @@ Error COFFWriter::finalize(bool IsBigObj) {
SizeOfHeaders +=
PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size();
}
- Obj.CoffFileHeader.NumberOfSections = Obj.Sections.size();
+ Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size();
SizeOfHeaders +=
IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header);
- SizeOfHeaders += sizeof(coff_section) * Obj.Sections.size();
+ SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size();
SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment);
Obj.CoffFileHeader.SizeOfOptionalHeader =
@@ -131,8 +173,8 @@ Error COFFWriter::finalize(bool IsBigObj) {
Obj.PeHeader.SizeOfHeaders = SizeOfHeaders;
Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData;
- if (!Obj.Sections.empty()) {
- const Section &S = Obj.Sections.back();
+ if (!Obj.getSections().empty()) {
+ const Section &S = Obj.getSections().back();
Obj.PeHeader.SizeOfImage =
alignTo(S.Header.VirtualAddress + S.Header.VirtualSize,
Obj.PeHeader.SectionAlignment);
@@ -198,7 +240,7 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
BigObjHeader.unused4 = 0;
// The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus
// get the original one instead.
- BigObjHeader.NumberOfSections = Obj.Sections.size();
+ BigObjHeader.NumberOfSections = Obj.getSections().size();
BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable;
BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols;
@@ -223,14 +265,14 @@ void COFFWriter::writeHeaders(bool IsBigObj) {
Ptr += sizeof(DD);
}
}
- for (const auto &S : Obj.Sections) {
+ for (const auto &S : Obj.getSections()) {
memcpy(Ptr, &S.Header, sizeof(S.Header));
Ptr += sizeof(S.Header);
}
}
void COFFWriter::writeSections() {
- for (const auto &S : Obj.Sections) {
+ for (const auto &S : Obj.getSections()) {
uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData;
std::copy(S.Contents.begin(), S.Contents.end(), Ptr);
@@ -295,7 +337,7 @@ Error COFFWriter::patchDebugDirectory() {
const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY];
if (Dir->Size <= 0)
return Error::success();
- for (const auto &S : Obj.Sections) {
+ for (const auto &S : Obj.getSections()) {
if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress &&
Dir->RelativeVirtualAddress <
S.Header.VirtualAddress + S.Header.SizeOfRawData) {
@@ -324,7 +366,7 @@ Error COFFWriter::patchDebugDirectory() {
}
Error COFFWriter::write() {
- bool IsBigObj = Obj.Sections.size() > MaxNumberOfSections16;
+ bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16;
if (IsBigObj && Obj.IsPE)
return make_error<StringError>("Too many sections for executable",
object_error::parse_failed);
OpenPOWER on IntegriCloud