Skip to content

Commit 5412ad5

Browse files
committed
[lldb] Address mask sbprocess apis and new mask invalid const (llvm#83663)
[lldb] Add SBProcess methods for get/set/use address masks (llvm#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. I originally landed this via llvm#83095 but it failed on CIs outside of arm64 Darwin so I had to debug it on more environments and update the patch. 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. This patch changes the value of "no mask set" from 0 to LLDB_INVALID_ADDRESS_MASK, which is UINT64_MAX. A mask of all 1's means "no bits are used for addressing" which is an impossible mask, whereas a mask of 0 means "all bits are used for addressing" which is possible. I added a base class implementation of ABI::FixCodeAddress and ABI::FixDataAddress that will apply the Process mask values if they are set to a value other than LLDB_INVALID_ADDRESS_MASK. I updated all the callers/users of the Mask methods which were handling a value of 0 to mean invalid mask to use LLDB_INVALID_ADDRESS_MASK. I added code to the all AArch64 ABI Fix* methods to apply the Highmem masks if they have been set. These will not be set on a Linux environment, but in TestAddressMasks.py I test the highmem masks feature for any AArch64 target, so all AArch64 ABI plugins must handle it. rdar://123530562 (cherry picked from commit aeaa11a) (cherry picked from commit 674487f)
1 parent 4ea8fb1 commit 5412ad5

File tree

19 files changed

+517
-45
lines changed

19 files changed

+517
-45
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/Target/ABI.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ class ABI : public PluginInterface {
122122
/// ARM uses bit zero to signify a code address is thumb, so any ARM ABI
123123
/// plug-ins would strip those bits.
124124
/// @{
125-
virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) { return pc; }
126-
virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) { return pc; }
125+
virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc);
126+
virtual lldb::addr_t FixDataAddress(lldb::addr_t pc);
127127
/// @}
128128

129129
/// Use this method when you do not know, or do not care what kind of address
@@ -166,10 +166,6 @@ class ABI : public PluginInterface {
166166
lldb::ProcessWP m_process_wp;
167167
std::unique_ptr<llvm::MCRegisterInfo> m_mc_register_info_up;
168168

169-
virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc, lldb::addr_t mask) {
170-
return pc;
171-
}
172-
173169
private:
174170
ABI(const ABI &) = delete;
175171
const ABI &operator=(const ABI &) = delete;

lldb/include/lldb/Target/Process.h

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,9 +1386,23 @@ class Process : public std::enable_shared_from_this<Process>,
13861386

13871387
virtual void DidExit() {}
13881388

1389+
/// Get the current address mask in the Process
1390+
///
1391+
/// This mask can used to set/clear non-address bits in an addr_t.
1392+
///
1393+
/// \return
1394+
/// The current address mask.
1395+
/// Bits which are set to 1 are not used for addressing.
1396+
/// An address mask of 0 means all bits are used for addressing.
1397+
/// An address mask of LLDB_INVALID_ADDRESS_MASK (all 1's) means
1398+
/// that no mask has been set.
13891399
lldb::addr_t GetCodeAddressMask();
13901400
lldb::addr_t GetDataAddressMask();
13911401

1402+
/// The highmem masks are for targets where we may have different masks
1403+
/// for low memory versus high memory addresses, and they will be left
1404+
/// as LLDB_INVALID_ADDRESS_MASK normally, meaning the base masks
1405+
/// should be applied to all addresses.
13921406
lldb::addr_t GetHighmemCodeAddressMask();
13931407
lldb::addr_t GetHighmemDataAddressMask();
13941408

@@ -3070,16 +3084,20 @@ void PruneThreadPlans();
30703084
/// from looking up or creating things during or after a finalize call.
30713085
std::atomic<bool> m_finalizing;
30723086

3073-
/// Mask for code an data addresses. The default value (0) means no mask is
3074-
/// set. The bits set to 1 indicate bits that are NOT significant for
3075-
/// addressing.
3076-
/// The highmem versions are for targets where we may have different masks
3077-
/// for low memory versus high memory addresses.
3087+
/// Mask for code an data addresses.
3088+
/// The default value LLDB_INVALID_ADDRESS_MASK means no mask has been set,
3089+
/// and addresses values should not be modified.
3090+
/// In these masks, the bits are set to 1 indicate bits that are not
3091+
/// significant for addressing.
3092+
/// The highmem masks are for targets where we may have different masks
3093+
/// for low memory versus high memory addresses, and they will be left
3094+
/// as LLDB_INVALID_ADDRESS_MASK normally, meaning the base masks
3095+
/// should be applied to all addresses.
30783096
/// @{
3079-
lldb::addr_t m_code_address_mask = 0;
3080-
lldb::addr_t m_data_address_mask = 0;
3081-
lldb::addr_t m_highmem_code_address_mask = 0;
3082-
lldb::addr_t m_highmem_data_address_mask = 0;
3097+
lldb::addr_t m_code_address_mask = LLDB_INVALID_ADDRESS_MASK;
3098+
lldb::addr_t m_data_address_mask = LLDB_INVALID_ADDRESS_MASK;
3099+
lldb::addr_t m_highmem_code_address_mask = LLDB_INVALID_ADDRESS_MASK;
3100+
lldb::addr_t m_highmem_data_address_mask = LLDB_INVALID_ADDRESS_MASK;
30833101
/// @}
30843102

30853103
bool m_clear_thread_plans_on_stop;

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
@@ -124,6 +124,11 @@
124124
#define MAX_PATH 260
125125
#endif
126126

127+
/// Address Mask
128+
/// Bits not used for addressing are set to 1 in the mask;
129+
/// all mask bits set is an invalid value.
130+
#define LLDB_INVALID_ADDRESS_MASK UINT64_MAX
131+
127132
// ignore GCC function attributes
128133
#if defined(_MSC_VER) && !defined(__clang__)
129134
#define __attribute__(X)

lldb/include/lldb/lldb-enumerations.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,22 @@ enum SymbolDownload {
13381338
eSymbolDownloadForeground = 2,
13391339
};
13401340

1341+
/// Used in the SBProcess AddressMask/FixAddress methods.
1342+
enum AddressMaskType {
1343+
eAddressMaskTypeCode = 0,
1344+
eAddressMaskTypeData,
1345+
eAddressMaskTypeAny,
1346+
eAddressMaskTypeAll = eAddressMaskTypeAny
1347+
};
1348+
1349+
/// Used in the SBProcess AddressMask/FixAddress methods.
1350+
enum AddressMaskRange {
1351+
eAddressMaskRangeLow = 0,
1352+
eAddressMaskRangeHigh,
1353+
eAddressMaskRangeAny,
1354+
eAddressMaskRangeAll = eAddressMaskRangeAny,
1355+
};
1356+
13411357
/// Specifies if children need to be re-computed
13421358
/// after a call to \ref SyntheticChildrenFrontEnd::Update.
13431359
enum class ChildCacheState {

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/Commands/CommandObjectProcess.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1453,7 +1453,7 @@ class CommandObjectProcessStatus : public CommandObjectParsed {
14531453
if (m_options.m_verbose) {
14541454
addr_t code_mask = process->GetCodeAddressMask();
14551455
addr_t data_mask = process->GetDataAddressMask();
1456-
if (code_mask != 0) {
1456+
if (code_mask != LLDB_INVALID_ADDRESS_MASK) {
14571457
int bits = std::bitset<64>(~code_mask).count();
14581458
result.AppendMessageWithFormat(
14591459
"Addressable code address mask: 0x%" PRIx64 "\n", code_mask);

0 commit comments

Comments
 (0)