llvm.org GIT mirror llvm / d55fc3f
Darwin: Add assembler directives to create version-min load commands. Allow object files to be tagged with a version-min load command for iOS or MacOSX. Teach macho-dump to understand the version-min load commands for testcases. rdar://11337778 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204190 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 6 years ago
15 changed file(s) with 240 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
1414 #include "llvm/ADT/SmallString.h"
1515 #include "llvm/ADT/ilist.h"
1616 #include "llvm/ADT/ilist_node.h"
17 #include "llvm/MC/MCDirectives.h"
1718 #include "llvm/MC/MCFixup.h"
1819 #include "llvm/MC/MCInst.h"
1920 #include "llvm/MC/MCSubtargetInfo.h"
839840 const_data_region_iterator;
840841 typedef std::vector::iterator data_region_iterator;
841842
843 /// MachO specific deployment target version info.
844 // A Major version of 0 indicates that no version information was supplied
845 // and so the corresponding load command should not be emitted.
846 typedef struct {
847 MCVersionMinType Kind;
848 unsigned Major;
849 unsigned Minor;
850 unsigned Update;
851 } VersionMinInfoType;
842852 private:
843853 MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION;
844854 void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION;
901911 // Access to the flags is necessary in cases where assembler directives affect
902912 // which flags to be set.
903913 unsigned ELFHeaderEFlags;
914
915 VersionMinInfoType VersionMinInfo;
904916 private:
905917 /// Evaluate a fixup to a relocatable expression and the value which should be
906918 /// placed into the fixup.
982994 unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;}
983995 void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;}
984996
997 /// MachO deployment target version information.
998 const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; }
999 void setVersionMinInfo(MCVersionMinType Kind, unsigned Major, unsigned Minor,
1000 unsigned Update) {
1001 VersionMinInfo.Kind = Kind;
1002 VersionMinInfo.Major = Major;
1003 VersionMinInfo.Minor = Minor;
1004 VersionMinInfo.Update = Update;
1005 }
1006
9851007 public:
9861008 /// Construct a new assembler instance.
9871009 ///
5959 MCDR_DataRegionEnd ///< .end_data_region
6060 };
6161
62 enum MCVersionMinType {
63 MCVM_IOSVersionMin, ///< .ios_version_min
64 MCVM_OSXVersionMin ///< .macosx_version_min
65 };
66
6267 } // end namespace llvm
6368
6469 #endif
384384
385385 /// EmitDataRegion - Note in the output the specified region @p Kind.
386386 virtual void EmitDataRegion(MCDataRegionType Kind) {}
387
388 /// EmitVersionMin - Specify the MachO minimum deployment target version.
389 virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor,
390 unsigned Update) {}
387391
388392 /// EmitThumbFunc - Note in the output that the specified @p Func is
389393 /// a Thumb mode function (ARM target only).
177177 getSegment64LoadCommand(const LoadCommandInfo &L) const;
178178 MachO::linker_options_command
179179 getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const;
180 MachO::version_min_command
181 getVersionMinLoadCommand(const LoadCommandInfo &L) const;
180182
181183 MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
182184 MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
132132 void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
133133 void EmitLinkerOptions(ArrayRef Options) override;
134134 void EmitDataRegion(MCDataRegionType Kind) override;
135 void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
136 unsigned Update) override;
135137 void EmitThumbFunc(MCSymbol *Func) override;
136138
137139 void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
376378 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
377379 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
378380 }
381 EmitEOL();
382 }
383
384 void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
385 unsigned Minor, unsigned Update) {
386 switch (Kind) {
387 case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break;
388 case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break;
389 }
390 OS << " " << Major << ", " << Minor;
391 if (Update)
392 OS << ", " << Update;
379393 EmitEOL();
380394 }
381395
295295 : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_),
296296 OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false),
297297 SubsectionsViaSymbols(false), ELFHeaderEFlags(0) {
298 VersionMinInfo.Major = 0; // Major version == 0 for "none specified"
298299 }
299300
300301 MCAssembler::~MCAssembler() {
4848 void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
4949 void EmitLinkerOptions(ArrayRef Options) override;
5050 void EmitDataRegion(MCDataRegionType Kind) override;
51 void EmitVersionMin(MCVersionMinType Kind, unsigned Major,
52 unsigned Minor, unsigned Update) override;
5153 void EmitThumbFunc(MCSymbol *Func) override;
5254 bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
5355 void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
190192 EmitDataRegionEnd();
191193 return;
192194 }
195 }
196
197 void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
198 unsigned Minor, unsigned Update) {
199 getAssembler().setVersionMinInfo(Kind, Major, Minor, Update);
193200 }
194201
195202 void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) {
162162 addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv");
163163
164164 addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident");
165 addDirectiveHandler<&DarwinAsmParser::ParseVersionMin>(".ios_version_min");
166 addDirectiveHandler<&DarwinAsmParser::ParseVersionMin>(
167 ".macosx_version_min");
165168 }
166169
167170 bool ParseDirectiveDesc(StringRef, SMLoc);
359362 return ParseSectionSwitch("__DATA", "__thread_init",
360363 MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
361364 }
365 bool ParseVersionMin(StringRef, SMLoc);
362366
363367 };
364368
858862 return false;
859863 }
860864
865 /// ParseVersionMin
866 /// ::= .ios_version_min major,minor[,update]
867 /// ::= .macosx_version_min major,minor[,update]
868 bool DarwinAsmParser::ParseVersionMin(StringRef Directive, SMLoc) {
869 int64_t Major = 0, Minor = 0, Update = 0;
870 int Kind = StringSwitch(Directive)
871 .Case(".ios_version_min", MCVM_IOSVersionMin)
872 .Case(".macosx_version_min", MCVM_OSXVersionMin);
873 // Get the major version number.
874 if (getLexer().isNot(AsmToken::Integer))
875 return TokError("invalid OS major version number");
876 Major = getLexer().getTok().getIntVal();
877 if (Major > 65535 || Major <= 0)
878 return TokError("invalid OS major version number");
879 Lex();
880 if (getLexer().isNot(AsmToken::Comma))
881 return TokError("minor OS version number required, comma expected");
882 Lex();
883 // Get the minor version number.
884 if (getLexer().isNot(AsmToken::Integer))
885 return TokError("invalid OS minor version number");
886 Minor = getLexer().getTok().getIntVal();
887 if (Minor > 255 || Minor < 0)
888 return TokError("invalid OS minor version number");
889 Lex();
890 // Get the update level, if specified
891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
892 if (getLexer().isNot(AsmToken::Comma))
893 return TokError("invalid update specifier, comma expected");
894 Lex();
895 if (getLexer().isNot(AsmToken::Integer))
896 return TokError("invalid OS update number");
897 Update = getLexer().getTok().getIntVal();
898 if (Update > 255 || Update < 0)
899 return TokError("invalid OS update number");
900 Lex();
901 }
902
903 // We've parsed a correct version specifier, so send it to the streamer.
904 getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
905
906 return false;
907 }
908
861909 namespace llvm {
862910
863911 MCAsmParserExtension *createDarwinAsmParser() {
736736 void MachObjectWriter::WriteObject(MCAssembler &Asm,
737737 const MCAsmLayout &Layout) {
738738 unsigned NumSections = Asm.size();
739 const MCAssembler::VersionMinInfoType &VersionInfo =
740 Layout.getAssembler().getVersionMinInfo();
739741
740742 // The section data starts after the header, the segment load command (and
741743 // section headers) and the symbol table.
743745 uint64_t LoadCommandsSize = is64Bit() ?
744746 sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
745747 sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
748
749 // Add the deployment target version info load command size, if used.
750 if (VersionInfo.Major != 0) {
751 ++NumLoadCommands;
752 LoadCommandsSize += sizeof(MachO::version_min_command);
753 }
746754
747755 // Add the data-in-code load command size, if used.
748756 unsigned NumDataRegions = Asm.getDataRegions().size();
814822 uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
815823 WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
816824 RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
825 }
826
827 // Write out the deployment target information, if it's available.
828 if (VersionInfo.Major != 0) {
829 assert(VersionInfo.Update < 256 && "unencodable update target version");
830 assert(VersionInfo.Minor < 256 && "unencodable minor target version");
831 assert(VersionInfo.Major < 65536 && "unencodable major target version");
832 uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
833 (VersionInfo.Major << 16);
834 Write32(VersionInfo.Kind == MCVM_OSXVersionMin ? MachO::LC_VERSION_MIN_MACOSX :
835 MachO::LC_VERSION_MIN_IPHONEOS);
836 Write32(sizeof(MachO::version_min_command));
837 Write32(EncodedVersion);
838 Write32(0); // reserved.
817839 }
818840
819841 // Write the data-in-code load command, if used.
210210 SwapValue(C.cmd);
211211 SwapValue(C.cmdsize);
212212 SwapValue(C.count);
213 }
214
215 template<>
216 void SwapStruct(MachO::version_min_command&C) {
217 SwapValue(C.cmd);
218 SwapValue(C.cmdsize);
219 SwapValue(C.version);
220 SwapValue(C.reserved);
213221 }
214222
215223 template<>
14661474 return getStruct(this, L.Ptr);
14671475 }
14681476
1477 MachO::version_min_command
1478 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1479 return getStruct(this, L.Ptr);
1480 }
1481
14691482 MachO::any_relocation_info
14701483 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
14711484 const char *P = reinterpret_cast(Rel.p);
0 // RUN: not llvm-mc -triple i386-apple-darwin %s 2> %t
1 // RUN: FileCheck %s < %t
2 // RUN: not llvm-mc -triple x86_64-apple-darwin %s 2> %t
3 // RUN: FileCheck %s < %t
4 // RUN: not llvm-mc -triple armv7-apple-ios %s 2> %t
5 // RUN: FileCheck %s < %t
6
7 .ios_version_min 5,2,257
8 .ios_version_min 5,256,1
9 .ios_version_min 5,-1,1
10 .ios_version_min 0,1,1
11 .ios_version_min 70000,1
12 .macosx_version_min 99,2,257
13 .macosx_version_min 50,256,1
14 .macosx_version_min 10,-1,1
15 .macosx_version_min 0,1,1
16 .macosx_version_min 70000,1
17
18
19 // CHECK: error: invalid OS update number
20 // CHECK: .ios_version_min 5,2,257
21 // CHECK: ^
22 // CHECK: error: invalid OS minor version number
23 // CHECK: .ios_version_min 5,256,1
24 // CHECK: ^
25 // CHECK: error: invalid OS minor version number
26 // CHECK: .ios_version_min 5,-1,1
27 // CHECK: ^
28 // CHECK: error: invalid OS major version number
29 // CHECK: .ios_version_min 0,1,1
30 // CHECK: ^
31 // CHECK: error: invalid OS major version number
32 // CHECK: .ios_version_min 70000,1
33 // CHECK: ^
34 // CHECK: error: invalid OS update number
35 // CHECK: .macosx_version_min 99,2,257
36 // CHECK: ^
37 // CHECK: error: invalid OS minor version number
38 // CHECK: .macosx_version_min 50,256,1
39 // CHECK: ^
40 // CHECK: error: invalid OS minor version number
41 // CHECK: .macosx_version_min 10,-1,1
42 // CHECK: ^
43 // CHECK: error: invalid OS major version number
44 // CHECK: .macosx_version_min 0,1,1
45 // CHECK: ^
46 // CHECK: error: invalid OS major version number
47 // CHECK: .macosx_version_min 70000,1
48 // CHECK: ^
0 // RUN: llvm-mc -triple i386-apple-darwin %s | FileCheck %s
1 // RUN: llvm-mc -triple x86_64-apple-darwin %s | FileCheck %s
2 // RUN: llvm-mc -triple armv7s-apple-ios %s | FileCheck %s
3
4 // Test the parsing of well-formed version-min directives.
5
6 .ios_version_min 5,2,0
7 .ios_version_min 3,2,1
8 .ios_version_min 5,0
9
10 // CHECK: .ios_version_min 5, 2
11 // CHECK: .ios_version_min 3, 2, 1
12 // CHECK: .ios_version_min 5, 0
13
14 .macosx_version_min 10,2,0
15 .macosx_version_min 10,8,1
16 .macosx_version_min 2,0
17
18 // CHECK: .macosx_version_min 10, 2
19 // CHECK: .macosx_version_min 10, 8, 1
20 // CHECK: .macosx_version_min 2, 0
0 // RUN: llvm-mc -triple armv7-apple-ios %s -filetype=obj -o - | macho-dump | FileCheck %s
1
2 // Test the formation of the version-min load command in the MachO.
3 // use a nonsense but well formed version.
4 .ios_version_min 99,8,7
5 // CHECK: (('command', 37)
6 // CHECK: ('size', 16)
7 // CHECK: ('version, 6490119)
8 // CHECK: ('reserved, 0)
9 // CHECK: ),
0 // RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o - | macho-dump | FileCheck %s
1
2 // Test the formation of the version-min load command in the MachO.
3 // use a nonsense but well formed version.
4 .macosx_version_min 25,3,1
5 // CHECK: (('command', 36)
6 // CHECK: ('size', 16)
7 // CHECK: ('version, 1639169)
8 // CHECK: ('reserved, 0)
9 // CHECK: ),
318318 return 0;
319319 }
320320
321 static int
322 DumpVersionMin(const MachOObjectFile &Obj,
323 const MachOObjectFile::LoadCommandInfo &LCI) {
324 MachO::version_min_command VMLC = Obj.getVersionMinLoadCommand(LCI);
325 outs() << " ('version, " << VMLC.version << ")\n"
326 << " ('reserved, " << VMLC.reserved << ")\n";
327 return 0;
328 }
329
321330 static int DumpLoadCommand(const MachOObjectFile &Obj,
322331 MachOObjectFile::LoadCommandInfo &LCI) {
323332 switch (LCI.C.cmd) {
337346 return DumpDataInCodeDataCommand(Obj, LCI);
338347 case MachO::LC_LINKER_OPTIONS:
339348 return DumpLinkerOptionsCommand(Obj, LCI);
349 case MachO::LC_VERSION_MIN_IPHONEOS:
350 case MachO::LC_VERSION_MIN_MACOSX:
351 return DumpVersionMin(Obj, LCI);
340352 default:
341353 Warning("unknown load command: " + Twine(LCI.C.cmd));
342354 return 0;