Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,12 @@ enum Format {
///< character arrays that can contain non printable
///< characters
eFormatAddressInfo, ///< Describe what an address points to (func + offset
///< with file/line, symbol + offset, data, etc)
eFormatHexFloat, ///< ISO C99 hex float string
eFormatInstruction, ///< Disassemble an opcode
eFormatVoid, ///< Do not print this
///< with file/line, symbol + offset, data, etc)
eFormatHexFloat, ///< ISO C99 hex float string
eFormatInstruction, ///< Disassemble an opcode
eFormatVoid, ///< Do not print this
eFormatUnicode8,
eFormatCheriotCapability,
kNumFormats
};

Expand Down
1 change: 1 addition & 0 deletions lldb/source/Commands/CommandObjectMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed {
case eFormatAddressInfo:
case eFormatHexFloat:
case eFormatInstruction:
case eFormatCheriotCapability:
case eFormatVoid:
result.AppendError("unsupported format for writing memory");
return;
Expand Down
108 changes: 108 additions & 0 deletions lldb/source/Core/DumpDataExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,114 @@ lldb::offset_t lldb_private::DumpDataExtractor(
}

switch (item_format) {
case eFormatCheriotCapability: {
if (item_byte_size != 8) {
s->Printf("error: unsupported byte size (%" PRIu64
") for cheriot capability format",
(uint64_t)item_byte_size);
return offset;
}

// Extract the raw bits of the capability.
uint64_t uval64 = DE.GetMaxU64(&offset, item_byte_size);
uint32_t addr = uval64;
uint32_t meta = (uval64 >> 32);
unsigned B = meta & 0x1FF;
unsigned T = (meta >> 9) & 0x1FF;
unsigned E = (meta >> 18) & 0xF;
unsigned otype = (meta >> 22) & 0x7;
std::bitset<6> perms = (meta >> 25) & 0x3F;

bool GL = perms[5];
bool LD = false;
bool MC = false;
bool SD = false;
bool SL = false;
bool LM = false;
bool LG = false;
bool SR = false;
bool EX = false;
bool U0 = false;
bool SE = false;
bool US = false;

// Cheriot capabilities pack 11 permissions into 6 bits,
// so decoding is non-trivial.
if (perms[4] && perms[3]) {
LD = MC = SD = true;
SL = perms[2];
LM = perms[1];
LD = perms[0];
} else if (perms[4] && !perms[3] && perms[2]) {
LD = MC = true;
LM = perms[1];
LG = perms[0];
} else if (perms[4] && !perms[3] && !perms[2] && !perms[1] && !perms[0]) {
SD = MC = true;
} else if (perms[4] && !perms[3] && !perms[2]) {
LD = perms[1];
SD = perms[0];
} else if (!perms[4] && perms[3]) {
EX = LD = MC = true;
SR = perms[2];
LM = perms[1];
LG = perms[0];
} else {
U0 = perms[2];
SE = perms[1];
US = perms[0];
}

// Render the permissions to a string.
std::string perm_string;
perm_string += GL ? 'G' : '-';
perm_string += ' ';
perm_string += LD ? 'R' : '-';
perm_string += SD ? 'W' : '-';
perm_string += MC ? 'c' : '-';
perm_string += LG ? 'g' : '-';
perm_string += LM ? 'm' : '-';
perm_string += SL ? 'l' : '-';
perm_string += ' ';
perm_string += EX ? 'X' : '-';
perm_string += SR ? 'a' : '-';
perm_string += ' ';
perm_string += SE ? 'S' : '-';
perm_string += US ? 'U' : '-';
perm_string += U0 ? '0' : '-';

// Decode otype, and present with a semantic string if possible.
if (otype != 0 && !EX)
otype += 8;
constexpr llvm::StringRef otypes[] = {
"[unsealed]",
"[IRQ inherit forward sentry]",
"[IRQ disable forward sentry]",
"[IRQ enable forward sentry]",
"[IRQ disable return sentry]",
"[IRQ enable return sentry]",
};
llvm::StringRef otype_str = (otype < sizeof(otypes)) ? otypes[otype] : "";

// Compute the base and top addresses for the bounds.
unsigned e = (E != 15) ? E : 24;
uint64_t a_top = addr >> (e + 9);
uint64_t a_mid = (addr >> e) & 0x1FF;
uint64_t a_hi = (a_mid < B) ? 1 : 0;
uint64_t t_hi = (T < B) ? 1 : 0;
uint64_t c_b = -a_hi;
uint64_t c_t = t_hi - a_hi;
uint64_t a_top_base = a_top + c_b;
uint64_t a_top_top = a_top + c_t;
uint64_t base = ((a_top_base << 9) + B) << e;
uint64_t top = ((a_top_top << 9) + T) << e;
uint64_t len = top - base;

s->Printf("0x%08x (v:? 0x%08llx-0x%08llx l:0x%llx o:0x%x%s p: %s)", addr,
base, top, len, otype, otype_str.data(), perm_string.c_str());

break;
}
case eFormatBoolean:
if (item_byte_size <= 8)
s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
Expand Down
1 change: 1 addition & 0 deletions lldb/source/DataFormatters/FormatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ static constexpr FormatInfo g_format_infos[] = {
{eFormatInstruction, 'i', "instruction"},
{eFormatVoid, 'v', "void"},
{eFormatUnicode8, 'u', "unicode8"},
{eFormatCheriotCapability, 'P', "cheriot capability"},
};

static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==
Expand Down
10 changes: 10 additions & 0 deletions lldb/unittests/Core/DumpDataExtractorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ TEST_F(DumpDataExtractorTest, Formats) {

// Has no special handling, intended for use elsewhere.
TestDump<int>(99, lldb::Format::eFormatVoid, "0x00000063");

// Cheriot capability formatting
TestDump<uint64_t>(0x7608d4cd00220b34, lldb::eFormatCheriotCapability,
"0x00220b34 (v:? 0x00220b34-0x002211a8 l:0x674 "
"o:0x0[unsealed] p: G RWc-m- -- ---)");
}

TEST_F(DumpDataExtractorTest, FormatCharArray) {
Expand Down Expand Up @@ -403,4 +408,9 @@ TEST_F(DumpDataExtractorTest, ItemByteSizeErrors) {
TestDumpWithItemByteSize(
17, lldb::Format::eFormatHexFloat,
"error: unsupported byte size (17) for hex float format");

// Cheriot capabilities must be 8 bytes.
TestDumpWithItemByteSize(
17, lldb::Format::eFormatCheriotCapability,
"error: unsupported byte size (17) for cheriot capability format");
}