Skip to content

Commit 9f7a25d

Browse files
committed
[CHERIoT] Add a "cheriot capability" memory/register formatter to LLDB.
1 parent fd09919 commit 9f7a25d

File tree

5 files changed

+126
-4
lines changed

5 files changed

+126
-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: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,115 @@ 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+
unsigned R = (meta >> 31) & 1;
434+
435+
bool GL = perms[5];
436+
bool LD = false;
437+
bool MC = false;
438+
bool SD = false;
439+
bool SL = false;
440+
bool LM = false;
441+
bool LG = false;
442+
bool SR = false;
443+
bool EX = false;
444+
bool U0 = false;
445+
bool SE = false;
446+
bool US = false;
447+
448+
// Cheriot capabilities pack 11 permissions into 6 bits,
449+
// so decoding is non-trivial.
450+
if (perms[4] && perms[3]) {
451+
LD = MC = SD = true;
452+
SL = perms[2];
453+
LM = perms[1];
454+
LD = perms[0];
455+
} else if (perms[4] && !perms[3] && perms[2]) {
456+
LD = MC = true;
457+
LM = perms[1];
458+
LG = perms[0];
459+
} else if (perms[4] && !perms[3] && !perms[2] && !perms[1] && !perms[0]) {
460+
SD = MC = true;
461+
} else if (perms[4] && !perms[3] && !perms[2]) {
462+
LD = perms[1];
463+
SD = perms[0];
464+
} else if (!perms[4] && perms[3]) {
465+
EX = LD = MC = true;
466+
SR = perms[2];
467+
LM = perms[1];
468+
LG = perms[0];
469+
} else {
470+
U0 = perms[2];
471+
SE = perms[1];
472+
US = perms[0];
473+
}
474+
475+
// Render the permissions to a string.
476+
std::string perm_string;
477+
perm_string += GL ? 'G' : '-';
478+
perm_string += ' ';
479+
perm_string += LD ? 'R' : '-';
480+
perm_string += SD ? 'W' : '-';
481+
perm_string += MC ? 'c' : '-';
482+
perm_string += LG ? 'g' : '-';
483+
perm_string += LM ? 'm' : '-';
484+
perm_string += SL ? 'l' : '-';
485+
perm_string += ' ';
486+
perm_string += EX ? 'X' : '-';
487+
perm_string += SR ? 'a' : '-';
488+
perm_string += ' ';
489+
perm_string += SE ? 'S' : '-';
490+
perm_string += US ? 'U' : '-';
491+
perm_string += U0 ? '0' : '-';
492+
493+
// Decode otype, and present with a semantic string if possible.
494+
if (otype != 0 && !EX)
495+
otype += 8;
496+
llvm::StringRef otypes[] = {
497+
", unsealed",
498+
", IRQ inherit forward sentry",
499+
", IRQ disable forward sentry",
500+
", IRQ enable forward sentry",
501+
", IRQ disable return sentry",
502+
", IRQ enable return sentry",
503+
};
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+
518+
s->Printf(
519+
"0x%08x {0x%08llx-0x%08llx l:0x%09llx} p=[%s] otype=[%d%s] R=%d",
520+
addr, base, top, (top - base), perm_string.c_str(), otype,
521+
((otype < sizeof(otypes)) ? otypes[otype].data() : ""), R);
522+
523+
break;
524+
}
416525
case eFormatBoolean:
417526
if (item_byte_size <= 8)
418527
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, '\0', "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 {0x00220b34-0x002211a8 l:0x000000674} p=[G "
279+
"RWc-m- -- ---] otype=[0, unsealed] R=0");
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)