mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-05 14:34:55 +00:00
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
This commit is contained in:
parent
802d81591a
commit
d55fc3f151
@ -15,6 +15,7 @@
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
@ -840,6 +841,15 @@ public:
|
||||
const_data_region_iterator;
|
||||
typedef std::vector<DataRegionData>::iterator data_region_iterator;
|
||||
|
||||
/// MachO specific deployment target version info.
|
||||
// A Major version of 0 indicates that no version information was supplied
|
||||
// and so the corresponding load command should not be emitted.
|
||||
typedef struct {
|
||||
MCVersionMinType Kind;
|
||||
unsigned Major;
|
||||
unsigned Minor;
|
||||
unsigned Update;
|
||||
} VersionMinInfoType;
|
||||
private:
|
||||
MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION;
|
||||
@ -902,6 +912,8 @@ private:
|
||||
// Access to the flags is necessary in cases where assembler directives affect
|
||||
// which flags to be set.
|
||||
unsigned ELFHeaderEFlags;
|
||||
|
||||
VersionMinInfoType VersionMinInfo;
|
||||
private:
|
||||
/// Evaluate a fixup to a relocatable expression and the value which should be
|
||||
/// placed into the fixup.
|
||||
@ -983,6 +995,16 @@ public:
|
||||
unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;}
|
||||
void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;}
|
||||
|
||||
/// MachO deployment target version information.
|
||||
const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; }
|
||||
void setVersionMinInfo(MCVersionMinType Kind, unsigned Major, unsigned Minor,
|
||||
unsigned Update) {
|
||||
VersionMinInfo.Kind = Kind;
|
||||
VersionMinInfo.Major = Major;
|
||||
VersionMinInfo.Minor = Minor;
|
||||
VersionMinInfo.Update = Update;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
///
|
||||
|
@ -60,6 +60,11 @@ enum MCDataRegionType {
|
||||
MCDR_DataRegionEnd ///< .end_data_region
|
||||
};
|
||||
|
||||
enum MCVersionMinType {
|
||||
MCVM_IOSVersionMin, ///< .ios_version_min
|
||||
MCVM_OSXVersionMin ///< .macosx_version_min
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -386,6 +386,10 @@ public:
|
||||
/// EmitDataRegion - Note in the output the specified region @p Kind.
|
||||
virtual void EmitDataRegion(MCDataRegionType Kind) {}
|
||||
|
||||
/// EmitVersionMin - Specify the MachO minimum deployment target version.
|
||||
virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor,
|
||||
unsigned Update) {}
|
||||
|
||||
/// EmitThumbFunc - Note in the output that the specified @p Func is
|
||||
/// a Thumb mode function (ARM target only).
|
||||
virtual void EmitThumbFunc(MCSymbol *Func) = 0;
|
||||
|
@ -178,6 +178,8 @@ public:
|
||||
getSegment64LoadCommand(const LoadCommandInfo &L) const;
|
||||
MachO::linker_options_command
|
||||
getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const;
|
||||
MachO::version_min_command
|
||||
getVersionMinLoadCommand(const LoadCommandInfo &L) const;
|
||||
|
||||
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
|
||||
MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -213,6 +213,14 @@ void SwapStruct(MachO::linker_options_command &C) {
|
||||
SwapValue(C.count);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -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);
|
||||
|
49
test/MC/AsmParser/version-min-diagnostics.s
Normal file
49
test/MC/AsmParser/version-min-diagnostics.s
Normal file
@ -0,0 +1,49 @@
|
||||
// RUN: not llvm-mc -triple i386-apple-darwin %s 2> %t
|
||||
// RUN: FileCheck %s < %t
|
||||
// RUN: not llvm-mc -triple x86_64-apple-darwin %s 2> %t
|
||||
// RUN: FileCheck %s < %t
|
||||
// RUN: not llvm-mc -triple armv7-apple-ios %s 2> %t
|
||||
// RUN: FileCheck %s < %t
|
||||
|
||||
.ios_version_min 5,2,257
|
||||
.ios_version_min 5,256,1
|
||||
.ios_version_min 5,-1,1
|
||||
.ios_version_min 0,1,1
|
||||
.ios_version_min 70000,1
|
||||
.macosx_version_min 99,2,257
|
||||
.macosx_version_min 50,256,1
|
||||
.macosx_version_min 10,-1,1
|
||||
.macosx_version_min 0,1,1
|
||||
.macosx_version_min 70000,1
|
||||
|
||||
|
||||
// CHECK: error: invalid OS update number
|
||||
// CHECK: .ios_version_min 5,2,257
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS minor version number
|
||||
// CHECK: .ios_version_min 5,256,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS minor version number
|
||||
// CHECK: .ios_version_min 5,-1,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS major version number
|
||||
// CHECK: .ios_version_min 0,1,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS major version number
|
||||
// CHECK: .ios_version_min 70000,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS update number
|
||||
// CHECK: .macosx_version_min 99,2,257
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS minor version number
|
||||
// CHECK: .macosx_version_min 50,256,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS minor version number
|
||||
// CHECK: .macosx_version_min 10,-1,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS major version number
|
||||
// CHECK: .macosx_version_min 0,1,1
|
||||
// CHECK: ^
|
||||
// CHECK: error: invalid OS major version number
|
||||
// CHECK: .macosx_version_min 70000,1
|
||||
// CHECK: ^
|
21
test/MC/AsmParser/version-min.s
Normal file
21
test/MC/AsmParser/version-min.s
Normal file
@ -0,0 +1,21 @@
|
||||
// RUN: llvm-mc -triple i386-apple-darwin %s | FileCheck %s
|
||||
// RUN: llvm-mc -triple x86_64-apple-darwin %s | FileCheck %s
|
||||
// RUN: llvm-mc -triple armv7s-apple-ios %s | FileCheck %s
|
||||
|
||||
// Test the parsing of well-formed version-min directives.
|
||||
|
||||
.ios_version_min 5,2,0
|
||||
.ios_version_min 3,2,1
|
||||
.ios_version_min 5,0
|
||||
|
||||
// CHECK: .ios_version_min 5, 2
|
||||
// CHECK: .ios_version_min 3, 2, 1
|
||||
// CHECK: .ios_version_min 5, 0
|
||||
|
||||
.macosx_version_min 10,2,0
|
||||
.macosx_version_min 10,8,1
|
||||
.macosx_version_min 2,0
|
||||
|
||||
// CHECK: .macosx_version_min 10, 2
|
||||
// CHECK: .macosx_version_min 10, 8, 1
|
||||
// CHECK: .macosx_version_min 2, 0
|
10
test/MC/MachO/ios-version-min-load-command.s
Normal file
10
test/MC/MachO/ios-version-min-load-command.s
Normal file
@ -0,0 +1,10 @@
|
||||
// RUN: llvm-mc -triple armv7-apple-ios %s -filetype=obj -o - | macho-dump | FileCheck %s
|
||||
|
||||
// Test the formation of the version-min load command in the MachO.
|
||||
// use a nonsense but well formed version.
|
||||
.ios_version_min 99,8,7
|
||||
// CHECK: (('command', 37)
|
||||
// CHECK: ('size', 16)
|
||||
// CHECK: ('version, 6490119)
|
||||
// CHECK: ('reserved, 0)
|
||||
// CHECK: ),
|
10
test/MC/MachO/osx-version-min-load-command.s
Normal file
10
test/MC/MachO/osx-version-min-load-command.s
Normal file
@ -0,0 +1,10 @@
|
||||
// RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o - | macho-dump | FileCheck %s
|
||||
|
||||
// Test the formation of the version-min load command in the MachO.
|
||||
// use a nonsense but well formed version.
|
||||
.macosx_version_min 25,3,1
|
||||
// CHECK: (('command', 36)
|
||||
// CHECK: ('size', 16)
|
||||
// CHECK: ('version, 1639169)
|
||||
// CHECK: ('reserved, 0)
|
||||
// CHECK: ),
|
@ -319,6 +319,15 @@ DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
DumpVersionMin(const MachOObjectFile &Obj,
|
||||
const MachOObjectFile::LoadCommandInfo &LCI) {
|
||||
MachO::version_min_command VMLC = Obj.getVersionMinLoadCommand(LCI);
|
||||
outs() << " ('version, " << VMLC.version << ")\n"
|
||||
<< " ('reserved, " << VMLC.reserved << ")\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DumpLoadCommand(const MachOObjectFile &Obj,
|
||||
MachOObjectFile::LoadCommandInfo &LCI) {
|
||||
switch (LCI.C.cmd) {
|
||||
@ -338,6 +347,9 @@ static int DumpLoadCommand(const MachOObjectFile &Obj,
|
||||
return DumpDataInCodeDataCommand(Obj, LCI);
|
||||
case MachO::LC_LINKER_OPTIONS:
|
||||
return DumpLinkerOptionsCommand(Obj, LCI);
|
||||
case MachO::LC_VERSION_MIN_IPHONEOS:
|
||||
case MachO::LC_VERSION_MIN_MACOSX:
|
||||
return DumpVersionMin(Obj, LCI);
|
||||
default:
|
||||
Warning("unknown load command: " + Twine(LCI.C.cmd));
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user