Skip to content

Commit f09f0a6

Browse files
felipepiovezanadrian-prantl
authored andcommitted
[lldb] Consider OP_addrx in DWARFExpression::Update_DW_OP_addr
This rewrites DW_OP_addrx inside DWARFExpression as an DW_OP_addr so that we can update addresses that are originally located in the debug_addr section. The full discussion behind this can be found in https://discourse.llvm.org/t/dwarfexpression-and-dw-op-addrx/71627/12, but a summary follows. When SymbolFileDWARF::ParseVariableDIE creates DWARFExpressions for variables whose location is an OP_addr, it knows how to remap addresses appropriately in the DebugMap case. It then calls DWARFExpression::Update_DW_OP_addr, which updates the value associated with OP_addr. However, when we have an OP_addrx, the update function does nothing. This makes sense, as the DWARFExpression does not have a mutable view of the debug_addr section. In non-DebugMap flows this is not an issue, as the debug_addr contains the correct addresses of variables. In DebugMap flows, this is problematic because the work done by RelinkOSOAddress is lost. By updating the OP to OP_addr, we can also update the address as required, We also explored the alternative of relinking the debug_addr section when we are initializing OSOs (InitOSO). However, this creates an inconsistent story for users of DWARFExpression::GetLocation_DW_OP_addr. This function returns an address without telling callers whether that address came from an OP_addr or an OP_addrx. If we preemptively relink OP_addrx results without doing the same for OP_addr results, then callers can’t know whether the address they got was an executable address or an object file address. In other words, they can’t know whether they need to call LinkOSOFileAddress on those results or not. This patch addresses the majority of test failures when enabling DWARF 5 for MachO (over 200 test failures). Differential Revision: https://reviews.llvm.org/D155198
1 parent a5f0b23 commit f09f0a6

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,33 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
408408
// the heap data so "m_data" will now correctly manage the heap data.
409409
m_data.SetData(encoder.GetDataBuffer());
410410
return true;
411-
} else {
412-
const offset_t op_arg_size =
413-
GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
414-
if (op_arg_size == LLDB_INVALID_OFFSET)
415-
break;
416-
offset += op_arg_size;
417411
}
412+
if (op == DW_OP_addrx) {
413+
// Replace DW_OP_addrx with DW_OP_addr, since we can't modify the
414+
// read-only debug_addr table.
415+
// Subtract one to account for the opcode.
416+
llvm::ArrayRef data_before_op = m_data.GetData().take_front(offset - 1);
417+
418+
// Read the addrx index to determine how many bytes it needs.
419+
const lldb::offset_t old_offset = offset;
420+
m_data.GetULEB128(&offset);
421+
if (old_offset == offset)
422+
return false;
423+
llvm::ArrayRef data_after_op = m_data.GetData().drop_front(offset);
424+
425+
DataEncoder encoder(m_data.GetByteOrder(), m_data.GetAddressByteSize());
426+
encoder.AppendData(data_before_op);
427+
encoder.AppendU8(DW_OP_addr);
428+
encoder.AppendAddress(file_addr);
429+
encoder.AppendData(data_after_op);
430+
m_data.SetData(encoder.GetDataBuffer());
431+
return true;
432+
}
433+
const offset_t op_arg_size =
434+
GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
435+
if (op_arg_size == LLDB_INVALID_OFFSET)
436+
break;
437+
offset += op_arg_size;
418438
}
419439
return false;
420440
}

lldb/unittests/Expression/DWARFExpressionTest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,11 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
522522
ASSERT_TRUE(evaluate(expr, status, result)) << status.ToError();
523523
ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress);
524524
ASSERT_EQ(result.GetScalar().UInt(), 0x5678u);
525+
526+
ASSERT_TRUE(expr.Update_DW_OP_addr(dwarf_cu, 0xdeadbeef));
527+
ASSERT_TRUE(evaluate(expr, status, result)) << status.ToError();
528+
ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress);
529+
ASSERT_EQ(result.GetScalar().UInt(), 0xdeadbeefu);
525530
}
526531

527532
class CustomSymbolFileDWARF : public SymbolFileDWARF {

0 commit comments

Comments
 (0)