Skip to content

Commit b9c085c

Browse files
committed
[CHERIoT] Add a "cheriot capability" memory/register formatter to LLDB.
1 parent 5aace89 commit b9c085c

File tree

5 files changed

+125
-4
lines changed

5 files changed

+125
-4
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,12 @@ enum Format {
195195
///< character arrays that can contain non printable
196196
///< characters
197197
eFormatAddressInfo, ///< Describe what an address points to (func + offset
198-
///< with file/line, symbol + offset, data, etc)
199-
eFormatHexFloat, ///< ISO C99 hex float string
200-
eFormatInstruction, ///< Disassemble an opcode
201-
eFormatVoid, ///< Do not print this
198+
///< with file/line, symbol + offset, data, etc)
199+
eFormatHexFloat, ///< ISO C99 hex float string
200+
eFormatInstruction, ///< Disassemble an opcode
201+
eFormatVoid, ///< Do not print this
202202
eFormatUnicode8,
203+
eFormatCheriotCapability,
203204
kNumFormats
204205
};
205206

lldb/source/Commands/CommandObjectMemory.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed {
13541354
case eFormatAddressInfo:
13551355
case eFormatHexFloat:
13561356
case eFormatInstruction:
1357+
case eFormatCheriotCapability:
13571358
case eFormatVoid:
13581359
result.AppendError("unsupported format for writing memory");
13591360
return;

lldb/source/Core/DumpDataExtractor.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,114 @@ lldb::offset_t lldb_private::DumpDataExtractor(
413413
}
414414

415415
switch (item_format) {
416+
case eFormatCheriotCapability: {
417+
if (item_byte_size != 8) {
418+
s->Printf("error: unsupported byte size (%" PRIu64
419+
") for cheriot capability format",
420+
(uint64_t)item_byte_size);
421+
return offset;
422+
}
423+
424+
// Extract the raw bits of the capability.
425+
uint64_t uval64 = DE.GetMaxU64(&offset, item_byte_size);
426+
uint32_t addr = uval64;
427+
uint32_t meta = (uval64 >> 32);
428+
unsigned B = meta & 0x1FF;
429+
unsigned T = (meta >> 9) & 0x1FF;
430+
unsigned E = (meta >> 18) & 0xF;
431+
unsigned otype = (meta >> 22) & 0x7;
432+
std::bitset<6> perms = (meta >> 25) & 0x3F;
433+
434+
bool GL = perms[5];
435+
bool LD = false;
436+
bool MC = false;
437+
bool SD = false;
438+
bool SL = false;
439+
bool LM = false;
440+
bool LG = false;
441+
bool SR = false;
442+
bool EX = false;
443+
bool U0 = false;
444+
bool SE = false;
445+
bool US = false;
446+
447+
// Cheriot capabilities pack 11 permissions into 6 bits,
448+
// so decoding is non-trivial.
449+
if (perms[4] && perms[3]) {
450+
LD = MC = SD = true;
451+
SL = perms[2];
452+
LM = perms[1];
453+
LD = perms[0];
454+
} else if (perms[4] && !perms[3] && perms[2]) {
455+
LD = MC = true;
456+
LM = perms[1];
457+
LG = perms[0];
458+
} else if (perms[4] && !perms[3] && !perms[2] && !perms[1] && !perms[0]) {
459+
SD = MC = true;
460+
} else if (perms[4] && !perms[3] && !perms[2]) {
461+
LD = perms[1];
462+
SD = perms[0];
463+
} else if (!perms[4] && perms[3]) {
464+
EX = LD = MC = true;
465+
SR = perms[2];
466+
LM = perms[1];
467+
LG = perms[0];
468+
} else {
469+
U0 = perms[2];
470+
SE = perms[1];
471+
US = perms[0];
472+
}
473+
474+
// Render the permissions to a string.
475+
std::string perm_string;
476+
perm_string += GL ? 'G' : '-';
477+
perm_string += ' ';
478+
perm_string += LD ? 'R' : '-';
479+
perm_string += SD ? 'W' : '-';
480+
perm_string += MC ? 'c' : '-';
481+
perm_string += LG ? 'g' : '-';
482+
perm_string += LM ? 'm' : '-';
483+
perm_string += SL ? 'l' : '-';
484+
perm_string += ' ';
485+
perm_string += EX ? 'X' : '-';
486+
perm_string += SR ? 'a' : '-';
487+
perm_string += ' ';
488+
perm_string += SE ? 'S' : '-';
489+
perm_string += US ? 'U' : '-';
490+
perm_string += U0 ? '0' : '-';
491+
492+
// Decode otype, and present with a semantic string if possible.
493+
if (otype != 0 && !EX)
494+
otype += 8;
495+
constexpr llvm::StringRef otypes[] = {
496+
"[unsealed]",
497+
"[IRQ inherit forward sentry]",
498+
"[IRQ disable forward sentry]",
499+
"[IRQ enable forward sentry]",
500+
"[IRQ disable return sentry]",
501+
"[IRQ enable return sentry]",
502+
};
503+
llvm::StringRef otype_str = (otype < sizeof(otypes)) ? otypes[otype] : "";
504+
505+
// Compute the base and top addresses for the bounds.
506+
unsigned e = (E != 15) ? E : 24;
507+
uint64_t a_top = addr >> (e + 9);
508+
uint64_t a_mid = (addr >> e) & 0x1FF;
509+
uint64_t a_hi = (a_mid < B) ? 1 : 0;
510+
uint64_t t_hi = (T < B) ? 1 : 0;
511+
uint64_t c_b = -a_hi;
512+
uint64_t c_t = t_hi - a_hi;
513+
uint64_t a_top_base = a_top + c_b;
514+
uint64_t a_top_top = a_top + c_t;
515+
uint64_t base = ((a_top_base << 9) + B) << e;
516+
uint64_t top = ((a_top_top << 9) + T) << e;
517+
uint64_t len = top - base;
518+
519+
s->Printf("0x%08x (v:? 0x%08llx-0x%08llx l:0x%llx o:0x%x%s p: %s)", addr,
520+
base, top, len, otype, otype_str.data(), perm_string.c_str());
521+
522+
break;
523+
}
416524
case eFormatBoolean:
417525
if (item_byte_size <= 8)
418526
s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,

lldb/source/DataFormatters/FormatManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static constexpr FormatInfo g_format_infos[] = {
7272
{eFormatInstruction, 'i', "instruction"},
7373
{eFormatVoid, 'v', "void"},
7474
{eFormatUnicode8, 'u', "unicode8"},
75+
{eFormatCheriotCapability, 'P', "cheriot capability"},
7576
};
7677

7778
static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==

lldb/unittests/Core/DumpDataExtractorTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ TEST_F(DumpDataExtractorTest, Formats) {
272272

273273
// Has no special handling, intended for use elsewhere.
274274
TestDump<int>(99, lldb::Format::eFormatVoid, "0x00000063");
275+
276+
// Cheriot capability formatting
277+
TestDump<uint64_t>(0x7608d4cd00220b34, lldb::eFormatCheriotCapability,
278+
"0x00220b34 (v:? 0x00220b34-0x002211a8 l:0x674 "
279+
"o:0x0[unsealed] p: G RWc-m- -- ---)");
275280
}
276281

277282
TEST_F(DumpDataExtractorTest, FormatCharArray) {
@@ -403,4 +408,9 @@ TEST_F(DumpDataExtractorTest, ItemByteSizeErrors) {
403408
TestDumpWithItemByteSize(
404409
17, lldb::Format::eFormatHexFloat,
405410
"error: unsupported byte size (17) for hex float format");
411+
412+
// Cheriot capabilities must be 8 bytes.
413+
TestDumpWithItemByteSize(
414+
17, lldb::Format::eFormatCheriotCapability,
415+
"error: unsupported byte size (17) for cheriot capability format");
406416
}

0 commit comments

Comments
 (0)