Skip to content

Commit

Permalink
[MC] Reject CFI advance_loc separated by a non-private label for Mach-O
Browse files Browse the repository at this point in the history
Due to Mach-O's .subsections_via_symbols mechanism, non-private labels cannot
appear between .cfi_startproc/.cfi_endproc. Compilers do not produce such
labels, but hand-written assembly may. Give an error. Unfortunately,
emitDwarfAdvanceFrameAddr generated MCExpr doesn't have location
informatin.

Note: evaluateKnownAbsolute is to force folding A-B to a constant even if A and
B are separate by a non-private label. The function is a workaround for some
Mach-O assembler issues and should generally be avoided.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D153167
  • Loading branch information
MaskRay committed Jun 26, 2023
1 parent 5a1cdcb commit 0b06727
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
16 changes: 10 additions & 6 deletions llvm/lib/MC/MCAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,16 +1110,20 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout,
return WasRelaxed;

MCContext &Context = Layout.getAssembler().getContext();
uint64_t OldSize = DF.getContents().size();
int64_t AddrDelta;
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
assert(Abs && "We created call frame with an invalid expression");
(void) Abs;
int64_t Value;
bool Abs = DF.getAddrDelta().evaluateAsAbsolute(Value, Layout);
if (!Abs) {
getContext().reportError(DF.getAddrDelta().getLoc(),
"invalid CFI advance_loc expression");
return false;
}

SmallVectorImpl<char> &Data = DF.getContents();
uint64_t OldSize = Data.size();
Data.clear();
DF.getFixups().clear();

MCDwarfFrameEmitter::encodeAdvanceLoc(Context, AddrDelta, Data);
MCDwarfFrameEmitter::encodeAdvanceLoc(Context, Value, Data);
return OldSize != Data.size();
}

Expand Down
21 changes: 21 additions & 0 deletions llvm/test/MC/MachO/cfi-advance-loc-err.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# RUN: not llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:

# CHECK-COUNT-4: <unknown>:0: error: invalid CFI advance_loc expression

.section __TEXT,__text
.globl _foo
_foo:
.cfi_startproc
subq $8, %rsp
.cfi_adjust_cfa_offset 8
subq $8, %rsp
.cfi_adjust_cfa_offset 8

tmp0: # non-private label cannot appear here
addq $8, %rsp
.cfi_adjust_cfa_offset -8
.tmp1: # non-private label cannot appear here
addq $8, %rsp
.cfi_adjust_cfa_offset -8
retq
.cfi_endproc

0 comments on commit 0b06727

Please sign in to comment.