diff options
author | Jim Grosbach <grosbach@apple.com> | 2014-03-18 22:09:05 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2014-03-18 22:09:05 +0000 |
commit | d55fc3f151f3167da4aa467cf2ff4038f82e3664 (patch) | |
tree | f178c30a8dc074fd457634ac48513b3bf1331fc8 /lib/MC | |
parent | 802d81591a1695604e0c78fbd76261d0900b5ee3 (diff) | |
download | llvm-d55fc3f151f3167da4aa467cf2ff4038f82e3664.tar.gz llvm-d55fc3f151f3167da4aa467cf2ff4038f82e3664.tar.bz2 llvm-d55fc3f151f3167da4aa467cf2ff4038f82e3664.tar.xz |
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
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 14 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 7 | ||||
-rw-r--r-- | lib/MC/MCParser/DarwinAsmParser.cpp | 48 | ||||
-rw-r--r-- | lib/MC/MachObjectWriter.cpp | 22 |
5 files changed, 92 insertions, 0 deletions
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 85263fec62..e28c56e7d3 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -133,6 +133,8 @@ public: void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; void EmitDataRegion(MCDataRegionType Kind) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, + unsigned Update) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; @@ -380,6 +382,18 @@ void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { EmitEOL(); } +void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) { + switch (Kind) { + case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break; + case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break; + } + OS << " " << Major << ", " << Minor; + if (Update) + OS << ", " << Update; + EmitEOL(); +} + void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { // This needs to emit to a temporary string to get properly quoted // MCSymbols when they have spaces in them. diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 89d7d19016..910295c5d2 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -296,6 +296,7 @@ MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false), SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { + VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } MCAssembler::~MCAssembler() { diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index fef7b6bd70..c932c3c375 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -49,6 +49,8 @@ public: void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; void EmitDataRegion(MCDataRegionType Kind) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) override; void EmitThumbFunc(MCSymbol *Func) override; bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; @@ -193,6 +195,11 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { } } +void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, + unsigned Minor, unsigned Update) { + getAssembler().setVersionMinInfo(Kind, Major, Minor, Update); +} + void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { // Remember that the function is a thumb function. Fixup and relocation // values will need adjusted. diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 81c2cf021c..dd7eccb237 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -163,6 +163,9 @@ public: addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); addDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); + addDirectiveHandler<&DarwinAsmParser::ParseVersionMin>(".ios_version_min"); + addDirectiveHandler<&DarwinAsmParser::ParseVersionMin>( + ".macosx_version_min"); } bool ParseDirectiveDesc(StringRef, SMLoc); @@ -360,6 +363,7 @@ public: return ParseSectionSwitch("__DATA", "__thread_init", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); } + bool ParseVersionMin(StringRef, SMLoc); }; @@ -859,6 +863,50 @@ bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { return false; } +/// ParseVersionMin +/// ::= .ios_version_min major,minor[,update] +/// ::= .macosx_version_min major,minor[,update] +bool DarwinAsmParser::ParseVersionMin(StringRef Directive, SMLoc) { + int64_t Major = 0, Minor = 0, Update = 0; + int Kind = StringSwitch<int>(Directive) + .Case(".ios_version_min", MCVM_IOSVersionMin) + .Case(".macosx_version_min", MCVM_OSXVersionMin); + // Get the major version number. + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS major version number"); + Major = getLexer().getTok().getIntVal(); + if (Major > 65535 || Major <= 0) + return TokError("invalid OS major version number"); + Lex(); + if (getLexer().isNot(AsmToken::Comma)) + return TokError("minor OS version number required, comma expected"); + Lex(); + // Get the minor version number. + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS minor version number"); + Minor = getLexer().getTok().getIntVal(); + if (Minor > 255 || Minor < 0) + return TokError("invalid OS minor version number"); + Lex(); + // Get the update level, if specified + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("invalid update specifier, comma expected"); + Lex(); + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS update number"); + Update = getLexer().getTok().getIntVal(); + if (Update > 255 || Update < 0) + return TokError("invalid OS update number"); + Lex(); + } + + // We've parsed a correct version specifier, so send it to the streamer. + getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update); + + return false; +} + namespace llvm { MCAsmParserExtension *createDarwinAsmParser() { diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index b3b593d315..ff55c978d6 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -737,6 +737,8 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); + const MCAssembler::VersionMinInfoType &VersionInfo = + Layout.getAssembler().getVersionMinInfo(); // The section data starts after the header, the segment load command (and // section headers) and the symbol table. @@ -745,6 +747,12 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); + // Add the deployment target version info load command size, if used. + if (VersionInfo.Major != 0) { + ++NumLoadCommands; + LoadCommandsSize += sizeof(MachO::version_min_command); + } + // Add the data-in-code load command size, if used. unsigned NumDataRegions = Asm.getDataRegions().size(); if (NumDataRegions) { @@ -817,6 +825,20 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); } + // Write out the deployment target information, if it's available. + if (VersionInfo.Major != 0) { + assert(VersionInfo.Update < 256 && "unencodable update target version"); + assert(VersionInfo.Minor < 256 && "unencodable minor target version"); + assert(VersionInfo.Major < 65536 && "unencodable major target version"); + uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) | + (VersionInfo.Major << 16); + Write32(VersionInfo.Kind == MCVM_OSXVersionMin ? MachO::LC_VERSION_MIN_MACOSX : + MachO::LC_VERSION_MIN_IPHONEOS); + Write32(sizeof(MachO::version_min_command)); + Write32(EncodedVersion); + Write32(0); // reserved. + } + // Write the data-in-code load command, if used. uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; if (NumDataRegions) { |