LLVM API Documentation
00001 //===-- X86MachObjectWriter.cpp - X86 Mach-O Writer -----------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/X86MCTargetDesc.h" 00011 #include "MCTargetDesc/X86FixupKinds.h" 00012 #include "llvm/ADT/Twine.h" 00013 #include "llvm/MC/MCAsmLayout.h" 00014 #include "llvm/MC/MCAssembler.h" 00015 #include "llvm/MC/MCContext.h" 00016 #include "llvm/MC/MCMachObjectWriter.h" 00017 #include "llvm/MC/MCSectionMachO.h" 00018 #include "llvm/MC/MCValue.h" 00019 #include "llvm/Support/ErrorHandling.h" 00020 #include "llvm/Support/Format.h" 00021 #include "llvm/Support/MachO.h" 00022 00023 using namespace llvm; 00024 00025 namespace { 00026 class X86MachObjectWriter : public MCMachObjectTargetWriter { 00027 bool RecordScatteredRelocation(MachObjectWriter *Writer, 00028 const MCAssembler &Asm, 00029 const MCAsmLayout &Layout, 00030 const MCFragment *Fragment, 00031 const MCFixup &Fixup, 00032 MCValue Target, 00033 unsigned Log2Size, 00034 uint64_t &FixedValue); 00035 void RecordTLVPRelocation(MachObjectWriter *Writer, 00036 const MCAssembler &Asm, 00037 const MCAsmLayout &Layout, 00038 const MCFragment *Fragment, 00039 const MCFixup &Fixup, 00040 MCValue Target, 00041 uint64_t &FixedValue); 00042 00043 void RecordX86Relocation(MachObjectWriter *Writer, 00044 const MCAssembler &Asm, 00045 const MCAsmLayout &Layout, 00046 const MCFragment *Fragment, 00047 const MCFixup &Fixup, 00048 MCValue Target, 00049 uint64_t &FixedValue); 00050 void RecordX86_64Relocation(MachObjectWriter *Writer, 00051 const MCAssembler &Asm, 00052 const MCAsmLayout &Layout, 00053 const MCFragment *Fragment, 00054 const MCFixup &Fixup, 00055 MCValue Target, 00056 uint64_t &FixedValue); 00057 public: 00058 X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, 00059 uint32_t CPUSubtype) 00060 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, 00061 /*UseAggressiveSymbolFolding=*/Is64Bit) {} 00062 00063 void RecordRelocation(MachObjectWriter *Writer, 00064 const MCAssembler &Asm, const MCAsmLayout &Layout, 00065 const MCFragment *Fragment, const MCFixup &Fixup, 00066 MCValue Target, uint64_t &FixedValue) override { 00067 if (Writer->is64Bit()) 00068 RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, 00069 FixedValue); 00070 else 00071 RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, 00072 FixedValue); 00073 } 00074 }; 00075 } 00076 00077 static bool isFixupKindRIPRel(unsigned Kind) { 00078 return Kind == X86::reloc_riprel_4byte || 00079 Kind == X86::reloc_riprel_4byte_movq_load; 00080 } 00081 00082 static unsigned getFixupKindLog2Size(unsigned Kind) { 00083 switch (Kind) { 00084 default: 00085 llvm_unreachable("invalid fixup kind!"); 00086 case FK_PCRel_1: 00087 case FK_Data_1: return 0; 00088 case FK_PCRel_2: 00089 case FK_Data_2: return 1; 00090 case FK_PCRel_4: 00091 // FIXME: Remove these!!! 00092 case X86::reloc_riprel_4byte: 00093 case X86::reloc_riprel_4byte_movq_load: 00094 case X86::reloc_signed_4byte: 00095 case FK_Data_4: return 2; 00096 case FK_Data_8: return 3; 00097 } 00098 } 00099 00100 void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer, 00101 const MCAssembler &Asm, 00102 const MCAsmLayout &Layout, 00103 const MCFragment *Fragment, 00104 const MCFixup &Fixup, 00105 MCValue Target, 00106 uint64_t &FixedValue) { 00107 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 00108 unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); 00109 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 00110 00111 // See <reloc.h>. 00112 uint32_t FixupOffset = 00113 Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); 00114 uint32_t FixupAddress = 00115 Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); 00116 int64_t Value = 0; 00117 unsigned Index = 0; 00118 unsigned IsExtern = 0; 00119 unsigned Type = 0; 00120 00121 Value = Target.getConstant(); 00122 00123 if (IsPCRel) { 00124 // Compensate for the relocation offset, Darwin x86_64 relocations only have 00125 // the addend and appear to have attempted to define it to be the actual 00126 // expression addend without the PCrel bias. However, instructions with data 00127 // following the relocation are not accommodated for (see comment below 00128 // regarding SIGNED{1,2,4}), so it isn't exactly that either. 00129 Value += 1LL << Log2Size; 00130 } 00131 00132 if (Target.isAbsolute()) { // constant 00133 // SymbolNum of 0 indicates the absolute section. 00134 Type = MachO::X86_64_RELOC_UNSIGNED; 00135 Index = 0; 00136 00137 // FIXME: I believe this is broken, I don't think the linker can understand 00138 // it. I think it would require a local relocation, but I'm not sure if that 00139 // would work either. The official way to get an absolute PCrel relocation 00140 // is to use an absolute symbol (which we don't support yet). 00141 if (IsPCRel) { 00142 IsExtern = 1; 00143 Type = MachO::X86_64_RELOC_BRANCH; 00144 } 00145 } else if (Target.getSymB()) { // A - B + constant 00146 const MCSymbol *A = &Target.getSymA()->getSymbol(); 00147 if (A->isTemporary()) 00148 A = &A->AliasedSymbol(); 00149 const MCSymbolData &A_SD = Asm.getSymbolData(*A); 00150 const MCSymbolData *A_Base = Asm.getAtom(&A_SD); 00151 00152 const MCSymbol *B = &Target.getSymB()->getSymbol(); 00153 if (B->isTemporary()) 00154 B = &B->AliasedSymbol(); 00155 const MCSymbolData &B_SD = Asm.getSymbolData(*B); 00156 const MCSymbolData *B_Base = Asm.getAtom(&B_SD); 00157 00158 // Neither symbol can be modified. 00159 if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || 00160 Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) 00161 report_fatal_error("unsupported relocation of modified symbol", false); 00162 00163 // We don't support PCrel relocations of differences. Darwin 'as' doesn't 00164 // implement most of these correctly. 00165 if (IsPCRel) 00166 report_fatal_error("unsupported pc-relative relocation of difference", 00167 false); 00168 00169 // The support for the situation where one or both of the symbols would 00170 // require a local relocation is handled just like if the symbols were 00171 // external. This is certainly used in the case of debug sections where the 00172 // section has only temporary symbols and thus the symbols don't have base 00173 // symbols. This is encoded using the section ordinal and non-extern 00174 // relocation entries. 00175 00176 // Darwin 'as' doesn't emit correct relocations for this (it ends up with a 00177 // single SIGNED relocation); reject it for now. Except the case where both 00178 // symbols don't have a base, equal but both NULL. 00179 if (A_Base == B_Base && A_Base) 00180 report_fatal_error("unsupported relocation with identical base", false); 00181 00182 // A subtraction expression where both symbols are undefined is a 00183 // non-relocatable expression. 00184 if (A->isUndefined() && B->isUndefined()) 00185 report_fatal_error("unsupported relocation with subtraction expression", 00186 false); 00187 00188 Value += Writer->getSymbolAddress(&A_SD, Layout) - 00189 (!A_Base ? 0 : Writer->getSymbolAddress(A_Base, Layout)); 00190 Value -= Writer->getSymbolAddress(&B_SD, Layout) - 00191 (!B_Base ? 0 : Writer->getSymbolAddress(B_Base, Layout)); 00192 00193 if (A_Base) { 00194 Index = A_Base->getIndex(); 00195 IsExtern = 1; 00196 } 00197 else { 00198 Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; 00199 IsExtern = 0; 00200 } 00201 Type = MachO::X86_64_RELOC_UNSIGNED; 00202 00203 MachO::any_relocation_info MRE; 00204 MRE.r_word0 = FixupOffset; 00205 MRE.r_word1 = ((Index << 0) | 00206 (IsPCRel << 24) | 00207 (Log2Size << 25) | 00208 (IsExtern << 27) | 00209 (Type << 28)); 00210 Writer->addRelocation(Fragment->getParent(), MRE); 00211 00212 if (B_Base) { 00213 Index = B_Base->getIndex(); 00214 IsExtern = 1; 00215 } 00216 else { 00217 Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; 00218 IsExtern = 0; 00219 } 00220 Type = MachO::X86_64_RELOC_SUBTRACTOR; 00221 } else { 00222 const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); 00223 const MCSymbolData &SD = Asm.getSymbolData(*Symbol); 00224 const MCSymbolData *Base = Asm.getAtom(&SD); 00225 00226 // Relocations inside debug sections always use local relocations when 00227 // possible. This seems to be done because the debugger doesn't fully 00228 // understand x86_64 relocation entries, and expects to find values that 00229 // have already been fixed up. 00230 if (Symbol->isInSection()) { 00231 const MCSectionMachO &Section = static_cast<const MCSectionMachO&>( 00232 Fragment->getParent()->getSection()); 00233 if (Section.hasAttribute(MachO::S_ATTR_DEBUG)) 00234 Base = nullptr; 00235 } 00236 00237 // x86_64 almost always uses external relocations, except when there is no 00238 // symbol to use as a base address (a local symbol with no preceding 00239 // non-local symbol). 00240 if (Base) { 00241 Index = Base->getIndex(); 00242 IsExtern = 1; 00243 00244 // Add the local offset, if needed. 00245 if (Base != &SD) 00246 Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); 00247 } else if (Symbol->isInSection() && !Symbol->isVariable()) { 00248 // The index is the section ordinal (1-based). 00249 Index = SD.getFragment()->getParent()->getOrdinal() + 1; 00250 IsExtern = 0; 00251 Value += Writer->getSymbolAddress(&SD, Layout); 00252 00253 if (IsPCRel) 00254 Value -= FixupAddress + (1 << Log2Size); 00255 } else if (Symbol->isVariable()) { 00256 const MCExpr *Value = Symbol->getVariableValue(); 00257 int64_t Res; 00258 bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, 00259 Writer->getSectionAddressMap()); 00260 if (isAbs) { 00261 FixedValue = Res; 00262 return; 00263 } else { 00264 report_fatal_error("unsupported relocation of variable '" + 00265 Symbol->getName() + "'", false); 00266 } 00267 } else { 00268 report_fatal_error("unsupported relocation of undefined symbol '" + 00269 Symbol->getName() + "'", false); 00270 } 00271 00272 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); 00273 if (IsPCRel) { 00274 if (IsRIPRel) { 00275 if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { 00276 // x86_64 distinguishes movq foo@GOTPCREL so that the linker can 00277 // rewrite the movq to an leaq at link time if the symbol ends up in 00278 // the same linkage unit. 00279 if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) 00280 Type = MachO::X86_64_RELOC_GOT_LOAD; 00281 else 00282 Type = MachO::X86_64_RELOC_GOT; 00283 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { 00284 Type = MachO::X86_64_RELOC_TLV; 00285 } else if (Modifier != MCSymbolRefExpr::VK_None) { 00286 report_fatal_error("unsupported symbol modifier in relocation", 00287 false); 00288 } else { 00289 Type = MachO::X86_64_RELOC_SIGNED; 00290 00291 // The Darwin x86_64 relocation format has a problem where it cannot 00292 // encode an address (L<foo> + <constant>) which is outside the atom 00293 // containing L<foo>. Generally, this shouldn't occur but it does 00294 // happen when we have a RIPrel instruction with data following the 00295 // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel 00296 // adjustment Darwin x86_64 uses, the offset is still negative and the 00297 // linker has no way to recognize this. 00298 // 00299 // To work around this, Darwin uses several special relocation types 00300 // to indicate the offsets. However, the specification or 00301 // implementation of these seems to also be incomplete; they should 00302 // adjust the addend as well based on the actual encoded instruction 00303 // (the additional bias), but instead appear to just look at the final 00304 // offset. 00305 switch (-(Target.getConstant() + (1LL << Log2Size))) { 00306 case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break; 00307 case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break; 00308 case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break; 00309 } 00310 } 00311 } else { 00312 if (Modifier != MCSymbolRefExpr::VK_None) 00313 report_fatal_error("unsupported symbol modifier in branch " 00314 "relocation", false); 00315 00316 Type = MachO::X86_64_RELOC_BRANCH; 00317 } 00318 } else { 00319 if (Modifier == MCSymbolRefExpr::VK_GOT) { 00320 Type = MachO::X86_64_RELOC_GOT; 00321 } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { 00322 // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which 00323 // case all we do is set the PCrel bit in the relocation entry; this is 00324 // used with exception handling, for example. The source is required to 00325 // include any necessary offset directly. 00326 Type = MachO::X86_64_RELOC_GOT; 00327 IsPCRel = 1; 00328 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { 00329 report_fatal_error("TLVP symbol modifier should have been rip-rel", 00330 false); 00331 } else if (Modifier != MCSymbolRefExpr::VK_None) 00332 report_fatal_error("unsupported symbol modifier in relocation", false); 00333 else { 00334 Type = MachO::X86_64_RELOC_UNSIGNED; 00335 unsigned Kind = Fixup.getKind(); 00336 if (Kind == X86::reloc_signed_4byte) 00337 report_fatal_error("32-bit absolute addressing is not supported in " 00338 "64-bit mode", false); 00339 } 00340 } 00341 } 00342 00343 // x86_64 always writes custom values into the fixups. 00344 FixedValue = Value; 00345 00346 // struct relocation_info (8 bytes) 00347 MachO::any_relocation_info MRE; 00348 MRE.r_word0 = FixupOffset; 00349 MRE.r_word1 = ((Index << 0) | 00350 (IsPCRel << 24) | 00351 (Log2Size << 25) | 00352 (IsExtern << 27) | 00353 (Type << 28)); 00354 Writer->addRelocation(Fragment->getParent(), MRE); 00355 } 00356 00357 bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer, 00358 const MCAssembler &Asm, 00359 const MCAsmLayout &Layout, 00360 const MCFragment *Fragment, 00361 const MCFixup &Fixup, 00362 MCValue Target, 00363 unsigned Log2Size, 00364 uint64_t &FixedValue) { 00365 uint64_t OriginalFixedValue = FixedValue; 00366 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 00367 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 00368 unsigned Type = MachO::GENERIC_RELOC_VANILLA; 00369 00370 // See <reloc.h>. 00371 const MCSymbol *A = &Target.getSymA()->getSymbol(); 00372 const MCSymbolData *A_SD = &Asm.getSymbolData(*A); 00373 00374 if (!A_SD->getFragment()) 00375 report_fatal_error("symbol '" + A->getName() + 00376 "' can not be undefined in a subtraction expression", 00377 false); 00378 00379 uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); 00380 uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); 00381 FixedValue += SecAddr; 00382 uint32_t Value2 = 0; 00383 00384 if (const MCSymbolRefExpr *B = Target.getSymB()) { 00385 const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); 00386 00387 if (!B_SD->getFragment()) 00388 report_fatal_error("symbol '" + B->getSymbol().getName() + 00389 "' can not be undefined in a subtraction expression", 00390 false); 00391 00392 // Select the appropriate difference relocation type. 00393 // 00394 // Note that there is no longer any semantic difference between these two 00395 // relocation types from the linkers point of view, this is done solely for 00396 // pedantic compatibility with 'as'. 00397 Type = A_SD->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF : 00398 (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF; 00399 Value2 = Writer->getSymbolAddress(B_SD, Layout); 00400 FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); 00401 } 00402 00403 // Relocations are written out in reverse order, so the PAIR comes first. 00404 if (Type == MachO::GENERIC_RELOC_SECTDIFF || 00405 Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 00406 // If the offset is too large to fit in a scattered relocation, 00407 // we're hosed. It's an unfortunate limitation of the MachO format. 00408 if (FixupOffset > 0xffffff) { 00409 char Buffer[32]; 00410 format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer)); 00411 Asm.getContext().FatalError(Fixup.getLoc(), 00412 Twine("Section too large, can't encode " 00413 "r_address (") + Buffer + 00414 ") into 24 bits of scattered " 00415 "relocation entry."); 00416 llvm_unreachable("fatal error returned?!"); 00417 } 00418 00419 MachO::any_relocation_info MRE; 00420 MRE.r_word0 = ((0 << 0) | // r_address 00421 (MachO::GENERIC_RELOC_PAIR << 24) | // r_type 00422 (Log2Size << 28) | 00423 (IsPCRel << 30) | 00424 MachO::R_SCATTERED); 00425 MRE.r_word1 = Value2; 00426 Writer->addRelocation(Fragment->getParent(), MRE); 00427 } else { 00428 // If the offset is more than 24-bits, it won't fit in a scattered 00429 // relocation offset field, so we fall back to using a non-scattered 00430 // relocation. This is a bit risky, as if the offset reaches out of 00431 // the block and the linker is doing scattered loading on this 00432 // symbol, things can go badly. 00433 // 00434 // Required for 'as' compatibility. 00435 if (FixupOffset > 0xffffff) { 00436 FixedValue = OriginalFixedValue; 00437 return false; 00438 } 00439 } 00440 00441 MachO::any_relocation_info MRE; 00442 MRE.r_word0 = ((FixupOffset << 0) | 00443 (Type << 24) | 00444 (Log2Size << 28) | 00445 (IsPCRel << 30) | 00446 MachO::R_SCATTERED); 00447 MRE.r_word1 = Value; 00448 Writer->addRelocation(Fragment->getParent(), MRE); 00449 return true; 00450 } 00451 00452 void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer, 00453 const MCAssembler &Asm, 00454 const MCAsmLayout &Layout, 00455 const MCFragment *Fragment, 00456 const MCFixup &Fixup, 00457 MCValue Target, 00458 uint64_t &FixedValue) { 00459 assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && 00460 !is64Bit() && 00461 "Should only be called with a 32-bit TLVP relocation!"); 00462 00463 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 00464 uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 00465 unsigned IsPCRel = 0; 00466 00467 // Get the symbol data. 00468 const MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol()); 00469 unsigned Index = SD_A->getIndex(); 00470 00471 // We're only going to have a second symbol in pic mode and it'll be a 00472 // subtraction from the picbase. For 32-bit pic the addend is the difference 00473 // between the picbase and the next address. For 32-bit static the addend is 00474 // zero. 00475 if (Target.getSymB()) { 00476 // If this is a subtraction then we're pcrel. 00477 uint32_t FixupAddress = 00478 Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); 00479 const MCSymbolData *SD_B = 00480 &Asm.getSymbolData(Target.getSymB()->getSymbol()); 00481 IsPCRel = 1; 00482 FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) + 00483 Target.getConstant()); 00484 FixedValue += 1ULL << Log2Size; 00485 } else { 00486 FixedValue = 0; 00487 } 00488 00489 // struct relocation_info (8 bytes) 00490 MachO::any_relocation_info MRE; 00491 MRE.r_word0 = Value; 00492 MRE.r_word1 = ((Index << 0) | 00493 (IsPCRel << 24) | 00494 (Log2Size << 25) | 00495 (1 << 27) | // r_extern 00496 (MachO::GENERIC_RELOC_TLV << 28)); // r_type 00497 Writer->addRelocation(Fragment->getParent(), MRE); 00498 } 00499 00500 void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer, 00501 const MCAssembler &Asm, 00502 const MCAsmLayout &Layout, 00503 const MCFragment *Fragment, 00504 const MCFixup &Fixup, 00505 MCValue Target, 00506 uint64_t &FixedValue) { 00507 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 00508 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 00509 00510 // If this is a 32-bit TLVP reloc it's handled a bit differently. 00511 if (Target.getSymA() && 00512 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { 00513 RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, 00514 FixedValue); 00515 return; 00516 } 00517 00518 // If this is a difference or a defined symbol plus an offset, then we need a 00519 // scattered relocation entry. Differences always require scattered 00520 // relocations. 00521 if (Target.getSymB()) { 00522 RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 00523 Target, Log2Size, FixedValue); 00524 return; 00525 } 00526 00527 // Get the symbol data, if any. 00528 const MCSymbolData *SD = nullptr; 00529 if (Target.getSymA()) 00530 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); 00531 00532 // If this is an internal relocation with an offset, it also needs a scattered 00533 // relocation entry. 00534 uint32_t Offset = Target.getConstant(); 00535 if (IsPCRel) 00536 Offset += 1 << Log2Size; 00537 // Try to record the scattered relocation if needed. Fall back to non 00538 // scattered if necessary (see comments in RecordScatteredRelocation() 00539 // for details). 00540 if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) && 00541 RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 00542 Target, Log2Size, FixedValue)) 00543 return; 00544 00545 // See <reloc.h>. 00546 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 00547 unsigned Index = 0; 00548 unsigned IsExtern = 0; 00549 unsigned Type = 0; 00550 00551 if (Target.isAbsolute()) { // constant 00552 // SymbolNum of 0 indicates the absolute section. 00553 // 00554 // FIXME: Currently, these are never generated (see code below). I cannot 00555 // find a case where they are actually emitted. 00556 Type = MachO::GENERIC_RELOC_VANILLA; 00557 } else { 00558 // Resolve constant variables. 00559 if (SD->getSymbol().isVariable()) { 00560 int64_t Res; 00561 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( 00562 Res, Layout, Writer->getSectionAddressMap())) { 00563 FixedValue = Res; 00564 return; 00565 } 00566 } 00567 00568 // Check whether we need an external or internal relocation. 00569 if (Writer->doesSymbolRequireExternRelocation(SD)) { 00570 IsExtern = 1; 00571 Index = SD->getIndex(); 00572 // For external relocations, make sure to offset the fixup value to 00573 // compensate for the addend of the symbol address, if it was 00574 // undefined. This occurs with weak definitions, for example. 00575 if (!SD->Symbol->isUndefined()) 00576 FixedValue -= Layout.getSymbolOffset(SD); 00577 } else { 00578 // The index is the section ordinal (1-based). 00579 const MCSectionData &SymSD = Asm.getSectionData( 00580 SD->getSymbol().getSection()); 00581 Index = SymSD.getOrdinal() + 1; 00582 FixedValue += Writer->getSectionAddress(&SymSD); 00583 } 00584 if (IsPCRel) 00585 FixedValue -= Writer->getSectionAddress(Fragment->getParent()); 00586 00587 Type = MachO::GENERIC_RELOC_VANILLA; 00588 } 00589 00590 // struct relocation_info (8 bytes) 00591 MachO::any_relocation_info MRE; 00592 MRE.r_word0 = FixupOffset; 00593 MRE.r_word1 = ((Index << 0) | 00594 (IsPCRel << 24) | 00595 (Log2Size << 25) | 00596 (IsExtern << 27) | 00597 (Type << 28)); 00598 Writer->addRelocation(Fragment->getParent(), MRE); 00599 } 00600 00601 MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS, 00602 bool Is64Bit, 00603 uint32_t CPUType, 00604 uint32_t CPUSubtype) { 00605 return createMachObjectWriter(new X86MachObjectWriter(Is64Bit, 00606 CPUType, 00607 CPUSubtype), 00608 OS, /*IsLittleEndian=*/true); 00609 }