Skip to content

Commit 9a12b0a

Browse files
authored
[lldb] Add SBProcess methods for get/set/use address masks (#83095)
I'm reviving a patch from phabracator, https://reviews.llvm.org/D155905 which was approved but I wasn't thrilled with all the API I was adding to SBProcess for all of the address mask types / memory regions. In this update, I added enums to control type address mask type (code, data, any) and address space specifiers (low, high, all) with defaulted arguments for the most common case. This patch is also fixing a bug in the "addressable bits to address mask" calculation I added in AddressableBits::SetProcessMasks. If lldb were told that 64 bits are valid for addressing, this method would overflow the calculation and set an invalid mask. Added tests to check this specific bug while I was adding these APIs. rdar://123530562
1 parent 5899599 commit 9a12b0a

File tree

10 files changed

+328
-6
lines changed

10 files changed

+328
-6
lines changed

lldb/include/lldb/API/SBProcess.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,120 @@ class LLDB_API SBProcess {
407407
/// the process isn't loaded from a core file.
408408
lldb::SBFileSpec GetCoreFile();
409409

410+
/// \{
411+
/// \group Mask Address Methods
412+
///
413+
/// \a type
414+
/// All of the methods in this group take \a type argument
415+
/// which is an AddressMaskType enum value.
416+
/// There can be different address masks for code addresses and
417+
/// data addresses, this argument can select which to get/set,
418+
/// or to use when clearing non-addressable bits from an address.
419+
/// This choice of mask can be important for example on AArch32
420+
/// systems. Where instructions where instructions start on even addresses,
421+
/// the 0th bit may be used to indicate that a function is thumb code. On
422+
/// such a target, the eAddressMaskTypeCode may clear the 0th bit from an
423+
/// address to get the actual address Whereas eAddressMaskTypeData would not.
424+
///
425+
/// \a addr_range
426+
/// Many of the methods in this group take an \a addr_range argument
427+
/// which is an AddressMaskRange enum value.
428+
/// Needing to specify the address range is highly unusual, and the
429+
/// default argument can be used in nearly all circumstances.
430+
/// On some architectures (e.g., AArch64), it is possible to have
431+
/// different page table setups for low and high memory, so different
432+
/// numbers of bits relevant to addressing. It is possible to have
433+
/// a program running in one half of memory and accessing the other
434+
/// as heap, so we need to maintain two different sets of address masks
435+
/// to debug this correctly.
436+
437+
/// Get the current address mask that will be applied to addresses
438+
/// before reading from memory.
439+
///
440+
/// \param[in] type
441+
/// See \ref Mask Address Methods description of this argument.
442+
/// eAddressMaskTypeAny is often a suitable value when code and
443+
/// data masks are the same on a given target.
444+
///
445+
/// \param[in] addr_range
446+
/// See \ref Mask Address Methods description of this argument.
447+
/// This will default to eAddressMaskRangeLow which is the
448+
/// only set of masks used normally.
449+
///
450+
/// \return
451+
/// The address mask currently in use. Bits which are not used
452+
/// for addressing will be set to 1 in the mask.
453+
lldb::addr_t GetAddressMask(
454+
lldb::AddressMaskType type,
455+
lldb::AddressMaskRange addr_range = lldb::eAddressMaskRangeLow);
456+
457+
/// Set the current address mask that can be applied to addresses
458+
/// before reading from memory.
459+
///
460+
/// \param[in] type
461+
/// See \ref Mask Address Methods description of this argument.
462+
/// eAddressMaskTypeAll is often a suitable value when the
463+
/// same mask is being set for both code and data.
464+
///
465+
/// \param[in] mask
466+
/// The address mask to set. Bits which are not used for addressing
467+
/// should be set to 1 in the mask.
468+
///
469+
/// \param[in] addr_range
470+
/// See \ref Mask Address Methods description of this argument.
471+
/// This will default to eAddressMaskRangeLow which is the
472+
/// only set of masks used normally.
473+
void SetAddressMask(
474+
lldb::AddressMaskType type, lldb::addr_t mask,
475+
lldb::AddressMaskRange addr_range = lldb::eAddressMaskRangeLow);
476+
477+
/// Set the number of bits used for addressing in this Process.
478+
///
479+
/// On Darwin and similar systems, the addressable bits are expressed
480+
/// as the number of low order bits that are relevant to addressing,
481+
/// instead of a more general address mask.
482+
/// This method calculates the correct mask value for a given number
483+
/// of low order addressable bits.
484+
///
485+
/// \param[in] type
486+
/// See \ref Mask Address Methods description of this argument.
487+
/// eAddressMaskTypeAll is often a suitable value when the
488+
/// same mask is being set for both code and data.
489+
///
490+
/// \param[in] num_bits
491+
/// Number of bits that are used for addressing.
492+
/// For example, a value of 42 indicates that the low 42 bits
493+
/// are relevant for addressing, and that higher-order bits may
494+
/// be used for various metadata like pointer authentication,
495+
/// Type Byte Ignore, etc.
496+
///
497+
/// \param[in] addr_range
498+
/// See \ref Mask Address Methods description of this argument.
499+
/// This will default to eAddressMaskRangeLow which is the
500+
/// only set of masks used normally.
501+
void
502+
SetAddressableBits(AddressMaskType type, uint32_t num_bits,
503+
AddressMaskRange addr_range = lldb::eAddressMaskRangeLow);
504+
505+
/// Clear the non-address bits of an \a addr value and return a
506+
/// virtual address in memory.
507+
///
508+
/// Bits that are not used in addressing may be used for other purposes;
509+
/// pointer authentication, or metadata in the top byte, or the 0th bit
510+
/// of armv7 code addresses to indicate arm/thumb are common examples.
511+
///
512+
/// \param[in] addr
513+
/// The address that should be cleared of non-address bits.
514+
///
515+
/// \param[in] type
516+
/// See \ref Mask Address Methods description of this argument.
517+
/// eAddressMaskTypeAny is the default value, correct when it
518+
/// is unknown if the address is a code or data address.
519+
lldb::addr_t
520+
FixAddress(lldb::addr_t addr,
521+
lldb::AddressMaskType type = lldb::eAddressMaskTypeAny);
522+
/// \}
523+
410524
/// Allocate memory within the process.
411525
///
412526
/// This function will allocate memory in the process's address space.

lldb/include/lldb/Utility/AddressableBits.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLDB_UTILITY_ADDRESSABLEBITS_H
1111

1212
#include "lldb/lldb-forward.h"
13+
#include "lldb/lldb-public.h"
1314

1415
namespace lldb_private {
1516

@@ -33,6 +34,8 @@ class AddressableBits {
3334

3435
void SetHighmemAddressableBits(uint32_t highmem_addressing_bits);
3536

37+
static lldb::addr_t AddressableBitToMask(uint32_t addressable_bits);
38+
3639
void SetProcessMasks(lldb_private::Process &process);
3740

3841
private:

lldb/include/lldb/lldb-defines.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@
127127
#define MAX_PATH 260
128128
#endif
129129

130+
/// Address Mask
131+
/// Bits not used for addressing are set to 1 in the mask;
132+
/// all mask bits set is an invalid value.
133+
#define LLDB_INVALID_ADDRESS_MASK UINT64_MAX
134+
130135
// ignore GCC function attributes
131136
#if defined(_MSC_VER) && !defined(__clang__)
132137
#define __attribute__(X)

lldb/include/lldb/lldb-enumerations.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,22 @@ enum SymbolDownload {
13231323
eSymbolDownloadForeground = 2,
13241324
};
13251325

1326+
/// Used in the SBProcess AddressMask/FixAddress methods.
1327+
enum AddressMaskType {
1328+
eAddressMaskTypeCode = 0,
1329+
eAddressMaskTypeData,
1330+
eAddressMaskTypeAny,
1331+
eAddressMaskTypeAll = eAddressMaskTypeAny
1332+
};
1333+
1334+
/// Used in the SBProcess AddressMask/FixAddress methods.
1335+
enum AddressMaskRange {
1336+
eAddressMaskRangeLow = 0,
1337+
eAddressMaskRangeHigh,
1338+
eAddressMaskRangeAny,
1339+
eAddressMaskRangeAll = eAddressMaskRangeAny,
1340+
};
1341+
13261342
} // namespace lldb
13271343

13281344
#endif // LLDB_LLDB_ENUMERATIONS_H

lldb/source/API/SBProcess.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,98 @@ lldb::SBFileSpec SBProcess::GetCoreFile() {
12551255
return SBFileSpec(core_file);
12561256
}
12571257

1258+
addr_t SBProcess::GetAddressMask(AddressMaskType type,
1259+
AddressMaskRange addr_range) {
1260+
LLDB_INSTRUMENT_VA(this, type, addr_range);
1261+
1262+
if (ProcessSP process_sp = GetSP()) {
1263+
switch (type) {
1264+
case eAddressMaskTypeCode:
1265+
if (addr_range == eAddressMaskRangeHigh)
1266+
return process_sp->GetHighmemCodeAddressMask();
1267+
else
1268+
return process_sp->GetCodeAddressMask();
1269+
case eAddressMaskTypeData:
1270+
if (addr_range == eAddressMaskRangeHigh)
1271+
return process_sp->GetHighmemDataAddressMask();
1272+
else
1273+
return process_sp->GetDataAddressMask();
1274+
case eAddressMaskTypeAny:
1275+
if (addr_range == eAddressMaskRangeHigh)
1276+
return process_sp->GetHighmemDataAddressMask();
1277+
else
1278+
return process_sp->GetDataAddressMask();
1279+
}
1280+
}
1281+
return LLDB_INVALID_ADDRESS_MASK;
1282+
}
1283+
1284+
void SBProcess::SetAddressMask(AddressMaskType type, addr_t mask,
1285+
AddressMaskRange addr_range) {
1286+
LLDB_INSTRUMENT_VA(this, type, mask, addr_range);
1287+
1288+
if (ProcessSP process_sp = GetSP()) {
1289+
switch (type) {
1290+
case eAddressMaskTypeCode:
1291+
if (addr_range == eAddressMaskRangeAll) {
1292+
process_sp->SetCodeAddressMask(mask);
1293+
process_sp->SetHighmemCodeAddressMask(mask);
1294+
} else if (addr_range == eAddressMaskRangeHigh) {
1295+
process_sp->SetHighmemCodeAddressMask(mask);
1296+
} else {
1297+
process_sp->SetCodeAddressMask(mask);
1298+
}
1299+
break;
1300+
case eAddressMaskTypeData:
1301+
if (addr_range == eAddressMaskRangeAll) {
1302+
process_sp->SetDataAddressMask(mask);
1303+
process_sp->SetHighmemDataAddressMask(mask);
1304+
} else if (addr_range == eAddressMaskRangeHigh) {
1305+
process_sp->SetHighmemDataAddressMask(mask);
1306+
} else {
1307+
process_sp->SetDataAddressMask(mask);
1308+
}
1309+
break;
1310+
case eAddressMaskTypeAll:
1311+
if (addr_range == eAddressMaskRangeAll) {
1312+
process_sp->SetCodeAddressMask(mask);
1313+
process_sp->SetDataAddressMask(mask);
1314+
process_sp->SetHighmemCodeAddressMask(mask);
1315+
process_sp->SetHighmemDataAddressMask(mask);
1316+
} else if (addr_range == eAddressMaskRangeHigh) {
1317+
process_sp->SetHighmemCodeAddressMask(mask);
1318+
process_sp->SetHighmemDataAddressMask(mask);
1319+
} else {
1320+
process_sp->SetCodeAddressMask(mask);
1321+
process_sp->SetDataAddressMask(mask);
1322+
}
1323+
break;
1324+
}
1325+
}
1326+
}
1327+
1328+
void SBProcess::SetAddressableBits(AddressMaskType type, uint32_t num_bits,
1329+
AddressMaskRange addr_range) {
1330+
LLDB_INSTRUMENT_VA(this, type, num_bits, addr_range);
1331+
1332+
SetAddressMask(type, AddressableBits::AddressableBitToMask(num_bits),
1333+
addr_range);
1334+
}
1335+
1336+
addr_t SBProcess::FixAddress(addr_t addr, AddressMaskType type) {
1337+
LLDB_INSTRUMENT_VA(this, addr, type);
1338+
1339+
if (ProcessSP process_sp = GetSP()) {
1340+
if (type == eAddressMaskTypeAny)
1341+
return process_sp->FixAnyAddress(addr);
1342+
else if (type == eAddressMaskTypeData)
1343+
return process_sp->FixDataAddress(addr);
1344+
else if (type == eAddressMaskTypeCode)
1345+
return process_sp->FixCodeAddress(addr);
1346+
}
1347+
return addr;
1348+
}
1349+
12581350
lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions,
12591351
lldb::SBError &sb_error) {
12601352
LLDB_INSTRUMENT_VA(this, size, permissions, sb_error);

lldb/source/Target/Process.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5682,29 +5682,31 @@ void Process::Flush() {
56825682

56835683
lldb::addr_t Process::GetCodeAddressMask() {
56845684
if (uint32_t num_bits_setting = GetVirtualAddressableBits())
5685-
return ~((1ULL << num_bits_setting) - 1);
5685+
return AddressableBits::AddressableBitToMask(num_bits_setting);
56865686

56875687
return m_code_address_mask;
56885688
}
56895689

56905690
lldb::addr_t Process::GetDataAddressMask() {
56915691
if (uint32_t num_bits_setting = GetVirtualAddressableBits())
5692-
return ~((1ULL << num_bits_setting) - 1);
5692+
return AddressableBits::AddressableBitToMask(num_bits_setting);
56935693

56945694
return m_data_address_mask;
56955695
}
56965696

56975697
lldb::addr_t Process::GetHighmemCodeAddressMask() {
56985698
if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
5699-
return ~((1ULL << num_bits_setting) - 1);
5699+
return AddressableBits::AddressableBitToMask(num_bits_setting);
5700+
57005701
if (m_highmem_code_address_mask)
57015702
return m_highmem_code_address_mask;
57025703
return GetCodeAddressMask();
57035704
}
57045705

57055706
lldb::addr_t Process::GetHighmemDataAddressMask() {
57065707
if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
5707-
return ~((1ULL << num_bits_setting) - 1);
5708+
return AddressableBits::AddressableBitToMask(num_bits_setting);
5709+
57085710
if (m_highmem_data_address_mask)
57095711
return m_highmem_data_address_mask;
57105712
return GetDataAddressMask();

lldb/source/Utility/AddressableBits.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,26 @@ void AddressableBits::SetHighmemAddressableBits(
3333
m_high_memory_addr_bits = highmem_addressing_bits;
3434
}
3535

36+
addr_t AddressableBits::AddressableBitToMask(uint32_t addressable_bits) {
37+
assert(addressable_bits <= sizeof(addr_t) * 8);
38+
if (addressable_bits == 64)
39+
return 0; // all bits used for addressing
40+
else
41+
return ~((1ULL << addressable_bits) - 1);
42+
}
43+
3644
void AddressableBits::SetProcessMasks(Process &process) {
3745
if (m_low_memory_addr_bits == 0 && m_high_memory_addr_bits == 0)
3846
return;
3947

4048
if (m_low_memory_addr_bits != 0) {
41-
addr_t low_addr_mask = ~((1ULL << m_low_memory_addr_bits) - 1);
49+
addr_t low_addr_mask = AddressableBitToMask(m_low_memory_addr_bits);
4250
process.SetCodeAddressMask(low_addr_mask);
4351
process.SetDataAddressMask(low_addr_mask);
4452
}
4553

4654
if (m_high_memory_addr_bits != 0) {
47-
addr_t hi_addr_mask = ~((1ULL << m_high_memory_addr_bits) - 1);
55+
addr_t hi_addr_mask = AddressableBitToMask(m_high_memory_addr_bits);
4856
process.SetHighmemCodeAddressMask(hi_addr_mask);
4957
process.SetHighmemDataAddressMask(hi_addr_mask);
5058
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C_SOURCES := main.c
2+
3+
include Makefile.rules

0 commit comments

Comments
 (0)