mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[XRay] Change Sled.Function to PC-relative for sled version 2 and make llvm-xray support sled version 2 addresses
Follow-up of D78082 and D78590. Otherwise, because xray_instr_map is now read-only, the absolute relocation used for Sled.Function will cause a text relocation.
This commit is contained in:
parent
f6be8705ff
commit
47a31a63f5
@ -280,7 +280,7 @@ public:
|
||||
const class Function *Fn;
|
||||
uint8_t Version;
|
||||
|
||||
void emit(int, MCStreamer *, const MCExpr *, const MCSymbol *) const;
|
||||
void emit(int, MCStreamer *) const;
|
||||
};
|
||||
|
||||
// All the sleds to be emitted.
|
||||
|
@ -50,6 +50,8 @@ struct SledEntry {
|
||||
|
||||
/// Whether the sled was annotated to always be instrumented.
|
||||
bool AlwaysInstrument;
|
||||
|
||||
unsigned char Version;
|
||||
};
|
||||
|
||||
struct YAMLXRaySledEntry {
|
||||
@ -59,6 +61,7 @@ struct YAMLXRaySledEntry {
|
||||
SledEntry::FunctionKinds Kind;
|
||||
bool AlwaysInstrument;
|
||||
std::string FunctionName;
|
||||
unsigned char Version;
|
||||
};
|
||||
|
||||
/// The InstrumentationMap represents the computed function id's and indicated
|
||||
@ -120,6 +123,7 @@ template <> struct MappingTraits<xray::YAMLXRaySledEntry> {
|
||||
IO.mapRequired("kind", Entry.Kind);
|
||||
IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
|
||||
IO.mapOptional("function-name", Entry.FunctionName);
|
||||
IO.mapOptional("version", Entry.Version, 0);
|
||||
}
|
||||
|
||||
static constexpr bool flow = true;
|
||||
|
@ -1767,6 +1767,8 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
|
||||
CurExceptionSym = nullptr;
|
||||
bool NeedsLocalForSize = MAI->needsLocalForSize();
|
||||
if (F.hasFnAttribute("patchable-function-entry") ||
|
||||
F.hasFnAttribute("function-instrument") ||
|
||||
F.hasFnAttribute("xray-instruction-threshold") ||
|
||||
needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize ||
|
||||
MF.getTarget().Options.EmitStackSizeSection) {
|
||||
CurrentFnBegin = createTempSymbol("func_begin");
|
||||
@ -3174,14 +3176,7 @@ void AsmPrinterHandler::markFunctionEnd() {}
|
||||
// In the binary's "xray_instr_map" section, an array of these function entries
|
||||
// describes each instrumentation point. When XRay patches your code, the index
|
||||
// into this table will be given to your handler as a patch point identifier.
|
||||
void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out,
|
||||
const MCExpr *Location,
|
||||
const MCSymbol *CurrentFnSym) const {
|
||||
if (Location)
|
||||
Out->emitValueImpl(Location, Bytes);
|
||||
else
|
||||
Out->emitSymbolValue(Sled, Bytes);
|
||||
Out->emitSymbolValue(CurrentFnSym, Bytes);
|
||||
void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out) const {
|
||||
auto Kind8 = static_cast<uint8_t>(Kind);
|
||||
Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1));
|
||||
Out->emitBinaryData(
|
||||
@ -3234,19 +3229,31 @@ void AsmPrinter::emitXRayTable() {
|
||||
// Now we switch to the instrumentation map section. Because this is done
|
||||
// per-function, we are able to create an index entry that will represent the
|
||||
// range of sleds associated with a function.
|
||||
auto &Ctx = OutContext;
|
||||
MCSymbol *SledsStart = OutContext.createTempSymbol("xray_sleds_start", true);
|
||||
OutStreamer->SwitchSection(InstMap);
|
||||
OutStreamer->emitLabel(SledsStart);
|
||||
for (const auto &Sled : Sleds) {
|
||||
const MCExpr *Location = nullptr;
|
||||
if (PCRel) {
|
||||
MCSymbol *Dot = OutContext.createTempSymbol();
|
||||
MCSymbol *Dot = Ctx.createTempSymbol();
|
||||
OutStreamer->emitLabel(Dot);
|
||||
Location = MCBinaryExpr::createSub(
|
||||
MCSymbolRefExpr::create(Sled.Sled, OutContext),
|
||||
MCSymbolRefExpr::create(Dot, OutContext), OutContext);
|
||||
OutStreamer->emitValueImpl(
|
||||
MCBinaryExpr::createSub(MCSymbolRefExpr::create(Sled.Sled, Ctx),
|
||||
MCSymbolRefExpr::create(Dot, Ctx), Ctx),
|
||||
WordSizeBytes);
|
||||
OutStreamer->emitValueImpl(
|
||||
MCBinaryExpr::createSub(
|
||||
MCSymbolRefExpr::create(CurrentFnBegin, Ctx),
|
||||
MCBinaryExpr::createAdd(
|
||||
MCSymbolRefExpr::create(Dot, Ctx),
|
||||
MCConstantExpr::create(WordSizeBytes, Ctx), Ctx),
|
||||
Ctx),
|
||||
WordSizeBytes);
|
||||
} else {
|
||||
OutStreamer->emitSymbolValue(Sled.Sled, WordSizeBytes);
|
||||
OutStreamer->emitSymbolValue(CurrentFnSym, WordSizeBytes);
|
||||
}
|
||||
Sled.emit(WordSizeBytes, OutStreamer.get(), Location, CurrentFnSym);
|
||||
Sled.emit(WordSizeBytes, OutStreamer.get());
|
||||
}
|
||||
MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true);
|
||||
OutStreamer->emitLabel(SledsEnd);
|
||||
|
@ -68,10 +68,13 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
|
||||
|
||||
StringRef Contents = "";
|
||||
const auto &Sections = ObjFile.getBinary()->sections();
|
||||
uint64_t Address = 0;
|
||||
auto I = llvm::find_if(Sections, [&](object::SectionRef Section) {
|
||||
Expected<StringRef> NameOrErr = Section.getName();
|
||||
if (NameOrErr)
|
||||
if (NameOrErr) {
|
||||
Address = Section.getAddress();
|
||||
return *NameOrErr == "xray_instr_map";
|
||||
}
|
||||
consumeError(NameOrErr.takeError());
|
||||
return false;
|
||||
});
|
||||
@ -141,6 +144,7 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
|
||||
return Address;
|
||||
};
|
||||
|
||||
const int WordSize = 8;
|
||||
int32_t FuncId = 1;
|
||||
uint64_t CurFn = 0;
|
||||
for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) {
|
||||
@ -165,6 +169,11 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
|
||||
std::make_error_code(std::errc::executable_format_error));
|
||||
Entry.Kind = Kinds[Kind];
|
||||
Entry.AlwaysInstrument = Extractor.getU8(&OffsetPtr) != 0;
|
||||
Entry.Version = Extractor.getU8(&OffsetPtr);
|
||||
if (Entry.Version >= 2) {
|
||||
Entry.Address += C - Contents.bytes_begin() + Address;
|
||||
Entry.Function += C - Contents.bytes_begin() + WordSize + Address;
|
||||
}
|
||||
|
||||
// We do replicate the function id generation scheme implemented in the
|
||||
// XRay runtime.
|
||||
@ -209,8 +218,8 @@ loadYAML(sys::fs::file_t Fd, size_t FileSize, StringRef Filename,
|
||||
for (const auto &Y : YAMLSleds) {
|
||||
FunctionAddresses[Y.FuncId] = Y.Function;
|
||||
FunctionIds[Y.Function] = Y.FuncId;
|
||||
Sleds.push_back(
|
||||
SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument});
|
||||
Sleds.push_back(SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument,
|
||||
Y.Version});
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
@ -7,30 +7,6 @@ define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always"
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_0:
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_0:
|
||||
; CHECK-MIPS64: b .Ltmp0
|
||||
; CHECK-MIPS32: b $tmp0
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64-LABEL: .Ltmp0:
|
||||
; CHECK-MIPS32-LABEL: $tmp0:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
ret i32 0
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_1:
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_1:
|
||||
; CHECK-MIPS64: b .Ltmp1
|
||||
; CHECK-MIPS32: b $tmp1
|
||||
; CHECK-NEXT: nop
|
||||
@ -51,21 +27,12 @@ define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always"
|
||||
; CHECK-MIPS64-LABEL: .Ltmp1:
|
||||
; CHECK-MIPS32-LABEL: $tmp1:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
}
|
||||
; CHECK: .section xray_instr_map,{{.*}}
|
||||
; CHECK-MIPS64: .8byte .Lxray_sled_0
|
||||
; CHECK-MIPS64: .8byte .Lxray_sled_1
|
||||
; CHECK-MIPS32: .4byte ($xray_sled_0)
|
||||
; CHECK-MIPS32: .4byte ($xray_sled_1)
|
||||
|
||||
; We test multiple returns in a single function to make sure we're getting all
|
||||
; of them with XRay instrumentation.
|
||||
define i32 @bar(i32 %i) nounwind noinline uwtable "function-instrument"="xray-always" {
|
||||
ret i32 0
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_2:
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_2:
|
||||
; CHECK-MIPS64: b .Ltmp2
|
||||
; CHECK-MIPS32: b $tmp2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_1:
|
||||
; CHECK-MIPS64-NEXT: b .Ltmp2
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_1:
|
||||
; CHECK-MIPS32-NEXT: b $tmp2
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
@ -84,41 +51,21 @@ define i32 @bar(i32 %i) nounwind noinline uwtable "function-instrument"="xray-al
|
||||
; CHECK-MIPS64-LABEL: .Ltmp2:
|
||||
; CHECK-MIPS32-LABEL: $tmp2:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
Test:
|
||||
%cond = icmp eq i32 %i, 0
|
||||
br i1 %cond, label %IsEqual, label %NotEqual
|
||||
IsEqual:
|
||||
ret i32 0
|
||||
}
|
||||
; CHECK: .section xray_instr_map,{{.*}}
|
||||
; CHECK-MIPS64: .8byte .Lxray_sled_0
|
||||
; CHECK-MIPS64: .8byte .Lxray_sled_1
|
||||
; CHECK-MIPS32: .4byte ($xray_sled_0)
|
||||
; CHECK-MIPS32: .4byte ($xray_sled_1)
|
||||
|
||||
; We test multiple returns in a single function to make sure we're getting all
|
||||
; of them with XRay instrumentation.
|
||||
define i32 @bar(i32 %i) nounwind noinline uwtable "function-instrument"="xray-always" {
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_3:
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_3:
|
||||
; CHECK-MIPS64: b .Ltmp3
|
||||
; CHECK-MIPS32: b $tmp3
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64-LABEL: .Ltmp3:
|
||||
; CHECK-MIPS32-LABEL: $tmp3:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
NotEqual:
|
||||
ret i32 1
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_4:
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_4:
|
||||
; CHECK-MIPS64: b .Ltmp4
|
||||
; CHECK-MIPS32: b $tmp4
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_2:
|
||||
; CHECK-MIPS64-NEXT: b .Ltmp4
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_2:
|
||||
; CHECK-MIPS32-NEXT: b $tmp4
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
@ -137,6 +84,59 @@ NotEqual:
|
||||
; CHECK-MIPS64-LABEL: .Ltmp4:
|
||||
; CHECK-MIPS32-LABEL: $tmp4:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
Test:
|
||||
%cond = icmp eq i32 %i, 0
|
||||
br i1 %cond, label %IsEqual, label %NotEqual
|
||||
IsEqual:
|
||||
ret i32 0
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_3:
|
||||
; CHECK-MIPS64-NEXT: b .Ltmp5
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_3:
|
||||
; CHECK-MIPS32-NEXT: b $tmp5
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64-LABEL: .Ltmp5:
|
||||
; CHECK-MIPS32-LABEL: $tmp5:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
NotEqual:
|
||||
ret i32 1
|
||||
; CHECK: .p2align 2
|
||||
; CHECK-MIPS64-LABEL: .Lxray_sled_4:
|
||||
; CHECK-MIPS64-NEXT: b .Ltmp6
|
||||
; CHECK-MIPS32-LABEL: $xray_sled_4:
|
||||
; CHECK-MIPS32-NEXT: b $tmp6
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64: nop
|
||||
; CHECK-MIPS64-LABEL: .Ltmp6:
|
||||
; CHECK-MIPS32-LABEL: $tmp6:
|
||||
; CHECK-MIPS32: addiu $25, $25, 52
|
||||
}
|
||||
; CHECK: .section xray_instr_map,{{.*}}
|
||||
; CHECK-MIPS64: .8byte .Lxray_sled_2
|
||||
|
@ -3,6 +3,8 @@
|
||||
; RUN: -relocation-model=pic < %s | FileCheck %s
|
||||
|
||||
define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK-NEXT: .Lfunc_begin0:
|
||||
; CHECK-LABEL: .Ltmp0:
|
||||
; CHECK: b .Ltmp1
|
||||
; CHECK-NEXT: nop
|
||||
@ -26,14 +28,14 @@ define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always"
|
||||
; CHECK: .Lxray_sleds_start0:
|
||||
; CHECK-NEXT: .Ltmp3:
|
||||
; CHECK-NEXT: .quad .Ltmp0-.Ltmp3
|
||||
; CHECK-NEXT: .quad foo
|
||||
; CHECK-NEXT: .quad .Lfunc_begin0-(.Ltmp3+8)
|
||||
; CHECK-NEXT: .byte 0x00
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
; CHECK-NEXT: .space 13
|
||||
; CHECK-NEXT: .Ltmp4:
|
||||
; CHECK-NEXT: .quad .Ltmp2-.Ltmp4
|
||||
; CHECK-NEXT: .quad foo
|
||||
; CHECK-NEXT: .quad .Lfunc_begin0-(.Ltmp4+8)
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
|
@ -6,17 +6,20 @@
|
||||
define i32 @callee(i32 %arg) nounwind noinline uwtable "function-instrument"="xray-always" "xray-log-args"="1" {
|
||||
ret i32 %arg
|
||||
}
|
||||
; CHECK-LABEL: callee:
|
||||
; CHECK-NEXT: Lfunc_begin0:
|
||||
|
||||
; CHECK-LABEL: Lxray_sleds_start0:
|
||||
; CHECK-NEXT: Ltmp0:
|
||||
; CHECK-NEXT: .quad {{\.?}}Lxray_sled_0-{{\.?}}Ltmp0
|
||||
; CHECK-NEXT: .quad {{_?}}callee
|
||||
; CHECK-NEXT: .quad {{\.?}}Lfunc_begin0-({{\.?}}Ltmp0+8)
|
||||
; CHECK-NEXT: .byte 0x03
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
; CHECK: .{{(zero|space)}} 13
|
||||
; CHECK: Ltmp1:
|
||||
; CHECK-NEXT: .quad {{\.?}}Lxray_sled_1-{{\.?}}Ltmp1
|
||||
; CHECK-NEXT: .quad {{_?}}callee
|
||||
; CHECK-NEXT: .quad {{\.?}}Lfunc_begin0-({{\.?}}Ltmp1+8)
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
@ -29,14 +32,14 @@ define i32 @caller(i32 %arg) nounwind noinline uwtable "function-instrument"="xr
|
||||
; CHECK-LABEL: Lxray_sleds_start1:
|
||||
; CHECK-NEXT: Ltmp3:
|
||||
; CHECK-NEXT: .quad {{\.?}}Lxray_sled_2-{{\.?}}Ltmp3
|
||||
; CHECK-NEXT: .quad {{_?}}caller
|
||||
; CHECK-NEXT: .quad {{\.?}}Lfunc_begin1-({{\.?}}Ltmp3+8)
|
||||
; CHECK-NEXT: .byte 0x03
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
; CHECK: .{{(zero|space)}} 13
|
||||
; CHECK: Ltmp4:
|
||||
; CHECK-NEXT: .quad {{\.?}}Lxray_sled_3-{{\.?}}Ltmp4
|
||||
; CHECK-NEXT: .quad {{_?}}caller
|
||||
; CHECK-NEXT: .quad {{\.?}}Lfunc_begin1-({{\.?}}Ltmp4+8)
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
; CHECK-NEXT: .byte 0x01
|
||||
; CHECK-NEXT: .byte 0x02
|
||||
|
@ -63,9 +63,9 @@ void exportAsYAML(const InstrumentationMap &Map, raw_ostream &OS,
|
||||
auto FuncId = Map.getFunctionId(Sled.Function);
|
||||
if (!FuncId)
|
||||
return;
|
||||
YAMLSleds.push_back({*FuncId, Sled.Address, Sled.Function, Sled.Kind,
|
||||
Sled.AlwaysInstrument,
|
||||
ExtractSymbolize ? FH.SymbolOrNumber(*FuncId) : ""});
|
||||
YAMLSleds.push_back(
|
||||
{*FuncId, Sled.Address, Sled.Function, Sled.Kind, Sled.AlwaysInstrument,
|
||||
ExtractSymbolize ? FH.SymbolOrNumber(*FuncId) : "", Sled.Version});
|
||||
}
|
||||
Output Out(OS, nullptr, 0);
|
||||
Out << YAMLSleds;
|
||||
|
Loading…
Reference in New Issue
Block a user