summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/WinCOFFObjectWriter.cpp
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2012-03-15 09:03:03 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2012-03-15 09:03:03 +0000
commitfa39bd2d42da0c3e20408bfd8fb28bc3633955dc (patch)
tree8ea51b7b3b0a3d227aeb08247e29d6ae9df6b969 /llvm/lib/MC/WinCOFFObjectWriter.cpp
parentd6533ccd48957d81a13399a48cf01f88e4840bb0 (diff)
downloadbcm5719-llvm-fa39bd2d42da0c3e20408bfd8fb28bc3633955dc.tar.gz
bcm5719-llvm-fa39bd2d42da0c3e20408bfd8fb28bc3633955dc.zip
Implement relocation-overflow behavior for PE/COFF.
This needs a test, but it will take some time to figure out the best way to get an input that will produce > 2^16 relocs. Patch by Graydon Hoare! llvm-svn: 152787
Diffstat (limited to 'llvm/lib/MC/WinCOFFObjectWriter.cpp')
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp31
1 files changed, 29 insertions, 2 deletions
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 7144e68b18b..f706cac8d36 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -783,9 +783,22 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
}
if (Sec->Relocations.size() > 0) {
- Sec->Header.NumberOfRelocations = Sec->Relocations.size();
+ bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
+
+ if (RelocationsOverflow) {
+ // Signal overflow by setting NumberOfSections to max value. Actual
+ // size is found in reloc #0. Microsoft tools understand this.
+ Sec->Header.NumberOfRelocations = 0xffff;
+ } else {
+ Sec->Header.NumberOfRelocations = Sec->Relocations.size();
+ }
Sec->Header.PointerToRelocations = offset;
+ if (RelocationsOverflow) {
+ // Reloc #0 will contain actual count, so make room for it.
+ offset += COFF::RelocationSize;
+ }
+
offset += COFF::RelocationSize * Sec->Relocations.size();
for (relocations::iterator cr = Sec->Relocations.begin(),
@@ -820,8 +833,12 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
MCAssembler::const_iterator j, je;
for (i = Sections.begin(), ie = Sections.end(); i != ie; i++)
- if ((*i)->Number != -1)
+ if ((*i)->Number != -1) {
+ if ((*i)->Relocations.size() >= 0xffff) {
+ (*i)->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
+ }
WriteSectionHeader((*i)->Header);
+ }
for (i = Sections.begin(), ie = Sections.end(),
j = Asm.begin(), je = Asm.end();
@@ -841,6 +858,16 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
assert(OS.tell() == (*i)->Header.PointerToRelocations &&
"Section::PointerToRelocations is insane!");
+ if ((*i)->Relocations.size() >= 0xffff) {
+ // In case of overflow, write actual relocation count as first
+ // relocation. Including the synthetic reloc itself (+ 1).
+ COFF::relocation r;
+ r.VirtualAddress = (*i)->Relocations.size() + 1;
+ r.SymbolTableIndex = 0;
+ r.Type = 0;
+ WriteRelocation(r);
+ }
+
for (relocations::const_iterator k = (*i)->Relocations.begin(),
ke = (*i)->Relocations.end();
k != ke; k++) {
OpenPOWER on IntegriCloud