summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/MC/MCAsmStreamer.cpp14
-rw-r--r--lib/MC/MCAssembler.cpp1
-rw-r--r--lib/MC/MCMachOStreamer.cpp7
-rw-r--r--lib/MC/MCParser/DarwinAsmParser.cpp48
-rw-r--r--lib/MC/MachObjectWriter.cpp22
-rw-r--r--lib/Object/MachOObjectFile.cpp13
6 files changed, 105 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) {
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 450693f64e..6b1dd87595 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -214,6 +214,14 @@ void SwapStruct(MachO::linker_options_command &C) {
}
template<>
+void SwapStruct(MachO::version_min_command&C) {
+ SwapValue(C.cmd);
+ SwapValue(C.cmdsize);
+ SwapValue(C.version);
+ SwapValue(C.reserved);
+}
+
+template<>
void SwapStruct(MachO::data_in_code_entry &C) {
SwapValue(C.offset);
SwapValue(C.length);
@@ -1467,6 +1475,11 @@ MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
return getStruct<MachO::linker_options_command>(this, L.Ptr);
}
+MachO::version_min_command
+MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::version_min_command>(this, L.Ptr);
+}
+
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
const char *P = reinterpret_cast<const char *>(Rel.p);