ARMMachObjectWriter.cpp revision 7b25ecf6adbf3c4709c48033acfeb6ebbb4452ab
151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===// 24241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// 34241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// The LLVM Compiler Infrastructure 44241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// 54241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// This file is distributed under the University of Illinois Open Source 64241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// License. See LICENSE.TXT for details. 74241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// 84241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//===----------------------------------------------------------------------===// 94241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek 1051125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek#include "MCTargetDesc/ARMBaseInfo.h" 1151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek#include "MCTargetDesc/ARMFixupKinds.h" 12b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin#include "llvm/ADT/Twine.h" 13b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin#include "llvm/MC/MCAssembler.h" 14b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin#include "llvm/MC/MCAsmLayout.h" 15b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin#include "llvm/MC/MCMachObjectWriter.h" 164241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/MC/MCContext.h" 174241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/MC/MCExpr.h" 184241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/MC/MCFixup.h" 195a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis#include "llvm/MC/MCFixupKindInfo.h" 205a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis#include "llvm/MC/MCMachOSymbolFlags.h" 214241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/MC/MCValue.h" 224a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek#include "llvm/Object/MachOFormat.h" 231309f9a3b225ea846e5822691c39a77423125505Ted Kremenek#include "llvm/Support/ErrorHandling.h" 2463bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenekusing namespace llvm; 254241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenekusing namespace llvm::object; 264241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek 27f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremeneknamespace { 284241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenekclass ARMMachObjectWriter : public MCMachObjectTargetWriter { 29ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek void RecordARMScatteredRelocation(MachObjectWriter *Writer, 304a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek const MCAssembler &Asm, 314a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek const MCAsmLayout &Layout, 3263bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenek const MCFragment *Fragment, 335fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek const MCFixup &Fixup, 3418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek MCValue Target, 35626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek unsigned Log2Size, 364241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek uint64_t &FixedValue); 374241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek void RecordARMMovwMovtRelocation(MachObjectWriter *Writer, 384a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek const MCAssembler &Asm, 3911062b118476368fa5b294954713e5df97d8599fTed Kremenek const MCAsmLayout &Layout, 405a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis const MCFragment *Fragment, 419ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek const MCFixup &Fixup, MCValue Target, 425a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis uint64_t &FixedValue); 435fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek 4411062b118476368fa5b294954713e5df97d8599fTed Kremenekpublic: 45cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, 46cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek uint32_t CPUSubtype) 47cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, 48cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek /*UseAggressiveSymbolFolding=*/true) {} 49cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void RecordRelocation(MachObjectWriter *Writer, 51bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu const MCAssembler &Asm, const MCAsmLayout &Layout, 52bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu const MCFragment *Fragment, const MCFixup &Fixup, 53bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu MCValue Target, uint64_t &FixedValue); 54c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu}; 5538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu} 56d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 57a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaksstatic bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, 58d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis unsigned &Log2Size) { 59d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis RelocType = unsigned(macho::RIT_Vanilla); 60d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis Log2Size = ~0U; 61e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenek 621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump switch (Kind) { 631833d284346b9fa11aae4e6aa07381347c04745cJordan Rose default: 641833d284346b9fa11aae4e6aa07381347c04745cJordan Rose return false; 651833d284346b9fa11aae4e6aa07381347c04745cJordan Rose 661833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case FK_Data_1: 671833d284346b9fa11aae4e6aa07381347c04745cJordan Rose Log2Size = llvm::Log2_32(1); 681833d284346b9fa11aae4e6aa07381347c04745cJordan Rose return true; 691833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case FK_Data_2: 701833d284346b9fa11aae4e6aa07381347c04745cJordan Rose Log2Size = llvm::Log2_32(2); 711833d284346b9fa11aae4e6aa07381347c04745cJordan Rose return true; 724c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek case FK_Data_4: 7346e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose Log2Size = llvm::Log2_32(4); 7446e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose return true; 7546e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case FK_Data_8: 761833d284346b9fa11aae4e6aa07381347c04745cJordan Rose Log2Size = llvm::Log2_32(8); 774c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek return true; 78d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek 794c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek // Handle 24-bit branch kinds. 8046e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_ldst_pcrel_12: 8146e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_pcrel_10: 8246e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_adr_pcrel_12: 831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case ARM::fixup_arm_condbranch: 8446e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_uncondbranch: 851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case ARM::fixup_arm_bl: 8646e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_blx: 871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RelocType = unsigned(macho::RIT_ARM_Branch24Bit); 885d5480380d7b7c3590a0283ddf239220e514e576Ted Kremenek // Report as 'long', even though that is not quite accurate. 891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Log2Size = llvm::Log2_32(4); 9046e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose return true; 911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 921833d284346b9fa11aae4e6aa07381347c04745cJordan Rose // Handle Thumb branches. 931833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case ARM::fixup_arm_thumb_br: 941833d284346b9fa11aae4e6aa07381347c04745cJordan Rose RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); 959c378f705405d37f49795d5e915989de774fe11fTed Kremenek Log2Size = llvm::Log2_32(2); 961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return true; 971833d284346b9fa11aae4e6aa07381347c04745cJordan Rose 981833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case ARM::fixup_t2_uncondbranch: 991833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case ARM::fixup_arm_thumb_bl: 1001833d284346b9fa11aae4e6aa07381347c04745cJordan Rose case ARM::fixup_arm_thumb_blx: 1011833d284346b9fa11aae4e6aa07381347c04745cJordan Rose RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); 102d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Log2Size = llvm::Log2_32(4); 103d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek return true; 1041833d284346b9fa11aae4e6aa07381347c04745cJordan Rose 105b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek case ARM::fixup_arm_movt_hi16: 10646e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_arm_movt_hi16_pcrel: 107f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek case ARM::fixup_t2_movt_hi16: 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case ARM::fixup_t2_movt_hi16_pcrel: 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RelocType = unsigned(macho::RIT_ARM_HalfDifference); 1104a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // Report as 'long', even though that is not quite accurate. 1114a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek Log2Size = llvm::Log2_32(4); 1124a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek return true; 1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1144323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek case ARM::fixup_arm_movw_lo16: 1158bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek case ARM::fixup_arm_movw_lo16_pcrel: 1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case ARM::fixup_t2_movw_lo16: 1174a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek case ARM::fixup_t2_movw_lo16_pcrel: 1184c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek RelocType = unsigned(macho::RIT_ARM_Half); 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Report as 'long', even though that is not quite accurate. 1204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek Log2Size = llvm::Log2_32(4); 1214c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek return true; 122c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu } 1234a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek} 124c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu 1258bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid ARMMachObjectWriter:: 1266800ba622e4edf287801ac69c42c61e7e294b06bAnna ZaksRecordARMMovwMovtRelocation(MachObjectWriter *Writer, 12746e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose const MCAssembler &Asm, 12846e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose const MCAsmLayout &Layout, 129e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenek const MCFragment *Fragment, 130e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenek const MCFixup &Fixup, 131a5888f61be9f8d76e9b48a453dbced50523bd2e0Argyrios Kyrtzidis MCValue Target, 132c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu uint64_t &FixedValue) { 1334a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 1340f9063c116b7c3b05d8042b5976463c2dae04861Ted Kremenek unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 135c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu unsigned Type = macho::RIT_ARM_Half; 1361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // See <reloc.h>. 13825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu const MCSymbol *A = &Target.getSymA()->getSymbol(); 13925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu MCSymbolData *A_SD = &Asm.getSymbolData(*A); 140955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks 141955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks if (!A_SD->getFragment()) 142955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks Asm.getContext().FatalError(Fixup.getLoc(), 143955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks "symbol '" + A->getName() + 1445032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu "' can not be undefined in a subtraction expression"); 1455032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu 1465032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); 1475032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu uint32_t Value2 = 0; 148b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu uint64_t SecAddr = 149b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu Writer->getSectionAddress(A_SD->getFragment()->getParent()); 150a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek FixedValue += SecAddr; 151a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek 152a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek if (const MCSymbolRefExpr *B = Target.getSymB()) { 153c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); 154c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu 1558bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek if (!B_SD->getFragment()) 156b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu Asm.getContext().FatalError(Fixup.getLoc(), 15752c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek "symbol '" + B->getSymbol().getName() + 15852c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek "' can not be undefined in a subtraction expression"); 159c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu 1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Select the appropriate difference relocation type. 1616800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks Type = macho::RIT_ARM_HalfDifference; 1621831bd29572b6a7243da73d9606209190c0217deBenjamin Kramer Value2 = Writer->getSymbolAddress(B_SD, Layout); 1636800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); 1645fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek } 165a5888f61be9f8d76e9b48a453dbced50523bd2e0Argyrios Kyrtzidis 1666800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks // Relocations are written out in reverse order, so the PAIR comes first. 1675fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: 168c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // 169c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // For these two r_type relocations they always have a pair following them and 1706800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks // the r_length bits are used differently. The encoding of the r_length is as 171c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // follows: 172c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // low bit of r_length: 1731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 0 - :lower16: for movw instructions 174c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // 1 - :upper16: for movt instructions 1759c378f705405d37f49795d5e915989de774fe11fTed Kremenek // high bit of r_length: 176c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // 0 - arm instructions 1774a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // 1 - thumb instructions 1784a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // the other half of the relocated expression is in the following pair 1794a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // relocation entry in the the low 16 bits of r_address field. 1800e8a3c743b9b3e3039e329a1736122d3b5b5fed9Ted Kremenek unsigned ThumbBit = 0; 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned MovtBit = 0; 182ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek switch ((unsigned)Fixup.getKind()) { 1834a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek default: break; 1845903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks case ARM::fixup_arm_movt_hi16: 1855903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks case ARM::fixup_arm_movt_hi16_pcrel: 1865903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks MovtBit = 1; 1875903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks // The thumb bit shouldn't be set in the 'other-half' bit of the 1889c378f705405d37f49795d5e915989de774fe11fTed Kremenek // relocation, but it will be set in FixedValue if the base symbol 18952c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek // is a thumb function. Clear it out here. 19052c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek if (A_SD->getFlags() & SF_ThumbFunc) 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FixedValue &= 0xfffffffe; 1929c378f705405d37f49795d5e915989de774fe11fTed Kremenek break; 19352c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek case ARM::fixup_t2_movt_hi16: 19452c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek case ARM::fixup_t2_movt_hi16_pcrel: 1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (A_SD->getFlags() & SF_ThumbFunc) 1964a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek FixedValue &= 0xfffffffe; 19746e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose MovtBit = 1; 1983148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek // Fallthrough 19946e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose case ARM::fixup_t2_movw_lo16: 2003148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek case ARM::fixup_t2_movw_lo16_pcrel: 2014a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek ThumbBit = 1; 202c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu break; 203c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu } 2044a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek 2054a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek if (Type == macho::RIT_ARM_HalfDifference) { 2064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek uint32_t OtherHalf = MovtBit 2071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); 2084a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek 2094a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek macho::RelocationEntry MRE; 2104a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek MRE.Word0 = ((OtherHalf << 0) | 2114a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek (macho::RIT_Pair << 24) | 212c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (MovtBit << 28) | 213c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (ThumbBit << 29) | 2144a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek (IsPCRel << 30) | 2154a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek macho::RF_Scattered); 2164a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek MRE.Word1 = Value2; 2174a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek Writer->addRelocation(Fragment->getParent(), MRE); 2184a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek } 2194a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek 2204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek macho::RelocationEntry MRE; 221c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu MRE.Word0 = ((FixupOffset << 0) | 222c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (Type << 24) | 2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump (MovtBit << 28) | 224c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (ThumbBit << 29) | 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump (IsPCRel << 30) | 226c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu macho::RF_Scattered); 227c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu MRE.Word1 = Value; 228c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu Writer->addRelocation(Fragment->getParent(), MRE); 2299c378f705405d37f49795d5e915989de774fe11fTed Kremenek} 230c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu 2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, 232c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const MCAssembler &Asm, 233d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek const MCAsmLayout &Layout, 234d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek const MCFragment *Fragment, 235d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek const MCFixup &Fixup, 236d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek MCValue Target, 237c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu unsigned Log2Size, 238c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu uint64_t &FixedValue) { 23938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 24038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 24199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie unsigned Type = macho::RIT_Vanilla; 24238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // See <reloc.h>. 244c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu const MCSymbol *A = &Target.getSymA()->getSymbol(); 24538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu MCSymbolData *A_SD = &Asm.getSymbolData(*A); 2469c378f705405d37f49795d5e915989de774fe11fTed Kremenek 2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (!A_SD->getFragment()) 2487177dee8aee4b432911c91f1b788963bec0cac9fDaniel Dunbar Asm.getContext().FatalError(Fixup.getLoc(), 24938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu "symbol '" + A->getName() + 2504a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek "' can not be undefined in a subtraction expression"); 2514a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek 25238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); 2534241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); 254d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis FixedValue += SecAddr; 255e96de2dfde487211fb52f9139cdcae64d051a406Zhongxing Xu uint32_t Value2 = 0; 2564241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek 257626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek if (const MCSymbolRefExpr *B = Target.getSymB()) { 2581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); 259626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek 2604241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek if (!B_SD->getFragment()) 2614241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek Asm.getContext().FatalError(Fixup.getLoc(), 2624241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek "symbol '" + B->getSymbol().getName() + 263626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek "' can not be undefined in a subtraction expression"); 2644241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek 265626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek // Select the appropriate difference relocation type. 266626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek Type = macho::RIT_Difference; 267626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek Value2 = Writer->getSymbolAddress(B_SD, Layout); 26838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); 26938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu } 27038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu 27138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // Relocations are written out in reverse order, so the PAIR comes first. 2725fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek if (Type == macho::RIT_Difference || 2735fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek Type == macho::RIT_Generic_LocalDifference) { 2745fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek macho::RelocationEntry MRE; 2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MRE.Word0 = ((0 << 0) | 27639b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek (macho::RIT_Pair << 24) | 27739b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek (Log2Size << 28) | 278d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek (IsPCRel << 30) | 279d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek macho::RF_Scattered); 2802ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek MRE.Word1 = Value2; 281d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Writer->addRelocation(Fragment->getParent(), MRE); 282d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek } 283626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek 284d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek macho::RelocationEntry MRE; 2854d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose MRE.Word0 = ((FixupOffset << 0) | 2864d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose (Type << 24) | 2874d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose (Log2Size << 28) | 2884d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose (IsPCRel << 30) | 2892ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek macho::RF_Scattered); 2902ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek MRE.Word1 = Value; 2914d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose Writer->addRelocation(Fragment->getParent(), MRE); 2924241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek} 29338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu 2946800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaksvoid ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, 2956800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks const MCAssembler &Asm, 29638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const MCAsmLayout &Layout, 2976800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks const MCFragment *Fragment, 29838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const MCFixup &Fixup, 2998bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek MCValue Target, 3006800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks uint64_t &FixedValue) { 30138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned Log2Size; 30338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu unsigned RelocType = macho::RIT_Vanilla; 304c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) 30538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // If we failed to get fixup kind info, it's because there's no legal 3064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // relocation type for the fixup kind. This happens when it's a fixup that's 3074241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek // expected to always be resolvable at assembly time and not have any 3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek // relocations needed. 309ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek Asm.getContext().FatalError(Fixup.getLoc(), 310ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek "unsupported relocation on symbol"); 311ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek 3124241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek // If this is a difference or a defined symbol plus an offset, then we need a 3134241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek // scattered relocation entry. Differences always require scattered 3149c378f705405d37f49795d5e915989de774fe11fTed Kremenek // relocations. 315ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek if (Target.getSymB()) { 316ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek if (RelocType == macho::RIT_ARM_Half || 317ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek RelocType == macho::RIT_ARM_HalfDifference) 31838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup, 3199d0064e802e81d0833e8ccab8978b17c0bac3625Ted Kremenek Target, FixedValue); 3204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 321d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Target, Log2Size, FixedValue); 322d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek } 3234241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek 3244a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek // Get the symbol data, if any. 3251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MCSymbolData *SD = 0; 32639b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek if (Target.getSymA()) 32739b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); 328c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu 3294241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek // FIXME: For other platforms, we need to use scattered relocations for 33038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // internal relocations with offsets. If this is an internal relocation with 33138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // an offset, it also needs a scattered relocation entry. 332626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek // 333626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek // Is this right for ARM? 334626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek uint32_t Offset = Target.getConstant(); 335626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek if (IsPCRel && RelocType == macho::RIT_Vanilla) 33638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu Offset += 1 << Log2Size; 33738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) 3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 33938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu Target, Log2Size, FixedValue); 3407ebde953bb050caa69f791fc1de449d435c6a36fTed Kremenek 34138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // See <reloc.h>. 3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 34338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu unsigned Index = 0; 3441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned IsExtern = 0; 34538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu unsigned Type = 0; 3461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 34738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu if (Target.isAbsolute()) { // constant 3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME! 34938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu report_fatal_error("FIXME: relocations to absolute targets " 3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump "not yet implemented"); 35138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu } else { 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Resolve constant variables. 3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (SD->getSymbol().isVariable()) { 3544241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek int64_t Res; 35538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Res, Layout, Writer->getSectionAddressMap())) { 35738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu FixedValue = Res; 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 35938b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu } 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 36138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu 36238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // Check whether we need an external or internal relocation. 3635fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek if (Writer->doesSymbolRequireExternRelocation(SD)) { 3645fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek IsExtern = 1; 36538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu Index = SD->getIndex(); 36638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu 36738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // For external relocations, make sure to offset the fixup value to 368c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu // compensate for the addend of the symbol address, if it was 369fe9e543a2a363df7fcaa899367d3b2580b63b27cTed Kremenek // undefined. This occurs with weak definitions, for example. 37038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu if (!SD->Symbol->isUndefined()) 371cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek FixedValue -= Layout.getSymbolOffset(SD); 37238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu } else { 37338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu // The index is the section ordinal (1-based). 37438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu const MCSectionData &SymSD = Asm.getSectionData( 37538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu SD->getSymbol().getSection()); 376d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Index = SymSD.getOrdinal() + 1; 377d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek FixedValue += Writer->getSectionAddress(&SymSD); 3782ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek } 3794d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose if (IsPCRel) 3804d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose FixedValue -= Writer->getSectionAddress(Fragment->getParent()); 3814d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose 382d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek // The type is determined by the fixup kind. 383d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Type = RelocType; 384d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek } 3852ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek 386841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek // struct relocation_info (8 bytes) 387841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek macho::RelocationEntry MRE; 388841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek MRE.Word0 = FixupOffset; 389841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek MRE.Word1 = ((Index << 0) | 3904241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek (IsPCRel << 24) | 391cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek (Log2Size << 25) | 392f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek (IsExtern << 27) | 393c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu (Type << 28)); 394f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek Writer->addRelocation(Fragment->getParent(), MRE); 3951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 396f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek 3979c378f705405d37f49795d5e915989de774fe11fTed KremenekMCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS, 398c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu bool Is64Bit, 399f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek uint32_t CPUType, 400f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek uint32_t CPUSubtype) { 4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit, 402f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek CPUType, 4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CPUSubtype), 4049c378f705405d37f49795d5e915989de774fe11fTed Kremenek OS, /*IsLittleEndian=*/true); 405c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu} 406f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek