diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-05-14 18:53:40 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-05-14 18:53:40 +0000 |
commit | 2493ddfe4218b68f03b38a4b0aabd3c962455329 (patch) | |
tree | 6685665adbe8776470c39ba88a71aaf08c3b2813 /llvm/lib/MC/MachObjectWriter.cpp | |
parent | 7070922ff8954467121a62bd2c2a6e6e0a0bfa86 (diff) | |
download | bcm5719-llvm-2493ddfe4218b68f03b38a4b0aabd3c962455329.tar.gz bcm5719-llvm-2493ddfe4218b68f03b38a4b0aabd3c962455329.zip |
MC/Mach-O/x86_64: Darwin's special "signed_N" relocation types should only be
used to replace a normal relocation, not a reference to a GOT entry.
llvm-svn: 103789
Diffstat (limited to 'llvm/lib/MC/MachObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/MachObjectWriter.cpp | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index 3ca67080053..00c14ef9de1 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -609,10 +609,31 @@ public: Type = RIT_X86_64_GOTLoad; else Type = RIT_X86_64_GOT; - } else if (Modifier != MCSymbolRefExpr::VK_None) + } else if (Modifier != MCSymbolRefExpr::VK_None) { report_fatal_error("unsupported symbol modifier in relocation"); - else + } else { Type = RIT_X86_64_Signed; + + // The Darwin x86_64 relocation format has a problem where it cannot + // encode an address (L<foo> + <constant>) which is outside the atom + // containing L<foo>. Generally, this shouldn't occur but it does + // happen when we have a RIPrel instruction with data following the + // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel + // adjustment Darwin x86_64 uses, the offset is still negative and + // the linker has no way to recognize this. + // + // To work around this, Darwin uses several special relocation types + // to indicate the offsets. However, the specification or + // implementation of these seems to also be incomplete; they should + // adjust the addend as well based on the actual encoded instruction + // (the additional bias), but instead appear to just look at the + // final offset. + switch (-(Target.getConstant() + (1LL << Log2Size))) { + case 1: Type = RIT_X86_64_Signed1; break; + case 2: Type = RIT_X86_64_Signed2; break; + case 4: Type = RIT_X86_64_Signed4; break; + } + } } else { if (Modifier != MCSymbolRefExpr::VK_None) report_fatal_error("unsupported symbol modifier in branch " @@ -620,27 +641,6 @@ public: Type = RIT_X86_64_Branch; } - - // The Darwin x86_64 relocation format has a problem where it cannot - // encode an address (L<foo> + <constant>) which is outside the atom - // containing L<foo>. Generally, this shouldn't occur but it does happen - // when we have a RIPrel instruction with data following the relocation - // entry (e.g., movb $012, L0(%rip)). Even with the PCrel adjustment - // Darwin x86_64 uses, the offset is still negative and the linker has - // no way to recognize this. - // - // To work around this, Darwin uses several special relocation types to - // indicate the offsets. However, the specification or implementation of - // these seems to also be incomplete; they should adjust the addend as - // well based on the actual encoded instruction (the additional bias), - // but instead appear to just look at the final offset. - if (IsRIPRel) { - switch (-(Target.getConstant() + (1LL << Log2Size))) { - case 1: Type = RIT_X86_64_Signed1; break; - case 2: Type = RIT_X86_64_Signed2; break; - case 4: Type = RIT_X86_64_Signed4; break; - } - } } else { if (Modifier == MCSymbolRefExpr::VK_GOT) { Type = RIT_X86_64_GOT; |