Skip to content

Commit

Permalink
Print stack offsets as relative to the current function's sp by default
Browse files Browse the repository at this point in the history
  • Loading branch information
chaoticgd committed Aug 9, 2024
1 parent 0144be2 commit f34cfed
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 37 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

## v2.1

- The offsets of stack variables will now be relative to the value of the stack pointer register for the current function rather than the caller by default.
- Variable symbols are no longer incorrectly deduplicated as if they were types.
- The static keyword is no longer missing from the output for static global variables.
- Structs defined inside global variable definitions are now printed with the correct C++ syntax.
- Fixed an issue where null addresses would be handled incorrectly.
- Fixed an issue where in some cases null addresses would be handled incorrectly.
- stdump: Added `--procedures` option.
- stdump: Added `--sort-by-address` option.
- stdump: Added `--caller-stack-offsets` option.

## v2.0

Expand Down
3 changes: 2 additions & 1 deletion docs/JsonFormat.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ and `ast_json.cpp` for the code that currently defines the format.

| Format Version | Release | Changes |
| - | - | - |
| 13 | | Added size_bytes field to all nodes. Renamed data_type_handle property to just data_type (since it's not a handle). |
| 14 | v2.1 | Added stack_frame_size property for function symbols. |
| 13 | v2.0 | Added size_bytes field to all nodes. Renamed data_type_handle property to just data_type (since it's not a handle). |
| 12 | | Added format and application properties to root object. Added hash property to function symbols. |
| 11 | | Lists of indices (instead of begin and end indices) are now used for relationships between symbols. |
| 10 | | Added modules as their own symbol type. Removed the text_address property of source file symbols. |
Expand Down
7 changes: 6 additions & 1 deletion src/ccc/mdebug_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ Result<void> LocalSymbolTableAnalyser::sub_source_file(const char* path, Address
return Result<void>();
}

Result<void> LocalSymbolTableAnalyser::procedure(const char* mangled_name, Address address, bool is_static)
Result<void> LocalSymbolTableAnalyser::procedure(
const char* mangled_name, Address address, const ProcedureDescriptor* procedure_descriptor, bool is_static)
{
if(!m_current_function || strcmp(mangled_name, m_current_function->mangled_name().c_str()) != 0) {
Result<void> result = create_function(mangled_name, address);
Expand All @@ -113,6 +114,10 @@ Result<void> LocalSymbolTableAnalyser::procedure(const char* mangled_name, Addre
m_current_function->storage_class = STORAGE_CLASS_STATIC;
}

if(procedure_descriptor) {
m_current_function->stack_frame_size = procedure_descriptor->frame_size;
}

return Result<void>();
}

Expand Down
3 changes: 2 additions & 1 deletion src/ccc/mdebug_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class LocalSymbolTableAnalyser {
Result<void> global_variable(
const char* mangled_name, Address address, const StabsType& type, bool is_static, GlobalStorageLocation location);
Result<void> sub_source_file(const char* name, Address text_address);
Result<void> procedure(const char* mangled_name, Address address, bool is_static);
Result<void> procedure(
const char* mangled_name, Address address, const ProcedureDescriptor* procedure_descriptor, bool is_static);
Result<void> label(const char* label, Address address, s32 line_number);
Result<void> text_end(const char* name, s32 function_size);
Result<void> function(const char* mangled_name, const StabsType& return_type, Address address);
Expand Down
4 changes: 2 additions & 2 deletions src/ccc/mdebug_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ Result<void> import_file(SymbolDatabase& database, const mdebug::File& input, co
case ParsedSymbolType::NON_STABS: {
if(symbol.raw->symbol_class == mdebug::SymbolClass::TEXT) {
if(symbol.raw->symbol_type == mdebug::SymbolType::PROC) {
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, false);
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, symbol.raw->procedure_descriptor, false);
CCC_RETURN_IF_ERROR(result);
} else if(symbol.raw->symbol_type == mdebug::SymbolType::STATICPROC) {
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, true);
Result<void> result = analyser.procedure(symbol.raw->string, symbol.raw->value, symbol.raw->procedure_descriptor, true);
CCC_RETURN_IF_ERROR(result);
} else if(symbol.raw->symbol_type == mdebug::SymbolType::LABEL) {
Result<void> result = analyser.label(symbol.raw->string, symbol.raw->value, symbol.raw->index);
Expand Down
23 changes: 15 additions & 8 deletions src/ccc/print_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ void CppPrinter::function(const Function& symbol, const SymbolDatabase& database
// Print out the parameter list.
fprintf(out, "(");
if(symbol.parameter_variables().has_value()) {
function_parameters(parameter_variables, database);
function_parameters(parameter_variables, database, symbol.stack_frame_size);
} else {
fprintf(out, "/* parameters unknown */");
}
Expand Down Expand Up @@ -240,7 +240,7 @@ void CppPrinter::function(const Function& symbol, const SymbolDatabase& database
}

if(const StackStorage* storage = std::get_if<StackStorage>(&variable->storage)) {
stack_storage_comment(*storage);
stack_storage_comment(*storage, symbol.stack_frame_size);
}

if(variable->type()) {
Expand Down Expand Up @@ -639,7 +639,7 @@ void CppPrinter::ast_node(
}
}

void CppPrinter::function_parameters(std::span<const ParameterVariable*> parameters, const SymbolDatabase& database)
void CppPrinter::function_parameters(std::span<const ParameterVariable*> parameters, const SymbolDatabase& database, s32 stack_frame_size)
{
bool skip_this = m_config.omit_this_parameter && !parameters.empty() && parameters[0]->name() == "this";
for(size_t i = skip_this ? 1 : 0; i < parameters.size(); i++) {
Expand All @@ -650,7 +650,7 @@ void CppPrinter::function_parameters(std::span<const ParameterVariable*> paramet
}

if(const StackStorage* storage = std::get_if<StackStorage>(&parameter_variable.storage)) {
stack_storage_comment(*storage);
stack_storage_comment(*storage, stack_frame_size);
}

VariableName variable_name;
Expand Down Expand Up @@ -757,14 +757,21 @@ void CppPrinter::register_storage_comment(const RegisterStorage& storage)
}
}

void CppPrinter::stack_storage_comment(const StackStorage& storage)
void CppPrinter::stack_storage_comment(const StackStorage& storage, s32 stack_frame_size)
{
if(m_config.print_storage_information) {
fprintf(out, "/* ");
if(storage.stack_pointer_offset >= 0) {
fprintf(out, "0x%x(sp)", storage.stack_pointer_offset);
s32 display_offset = storage.stack_pointer_offset;
const char* prefix = "";
if(stack_frame_size > -1 && !m_config.caller_stack_offsets) {
display_offset += stack_frame_size;
} else {
fprintf(out, "-0x%x(sp)", -storage.stack_pointer_offset);
prefix = "caller ";
}
if(display_offset >= 0) {
fprintf(out, "0x%x(%ssp)", display_offset, prefix);
} else {
fprintf(out, "-0x%x(%ssp)", -display_offset, prefix);
}
fprintf(out, " */ ");
}
Expand Down
5 changes: 3 additions & 2 deletions src/ccc/print_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct CppPrinterConfig {
bool omit_this_parameter : 1 = false;
bool substitute_parameter_lists : 1 = false;
bool skip_member_functions_outside_types : 1 = false;
bool caller_stack_offsets : 1 = false;
};

class CppPrinter {
Expand Down Expand Up @@ -57,11 +58,11 @@ class CppPrinter {
const SymbolDatabase& database,
SymbolDescriptor symbol_descriptor,
bool print_body = true);
void function_parameters(std::span<const ParameterVariable*> parameters, const SymbolDatabase& database);
void function_parameters(std::span<const ParameterVariable*> parameters, const SymbolDatabase& database, s32 stack_frame_size = -1);
void refined_data(const RefinedData& data, s32 indentation_level);
void global_storage_comment(const GlobalStorage& storage, Address address);
void register_storage_comment(const RegisterStorage& storage);
void stack_storage_comment(const StackStorage& storage);
void stack_storage_comment(const StackStorage& storage, s32 stack_frame_size = -1);
void offset(const ast::Node& node, s32 base_offset);

CppPrinterConfig m_config;
Expand Down
1 change: 1 addition & 0 deletions src/ccc/symbol_database.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ class Function : public Symbol {

std::string relative_path;
StorageClass storage_class;
s32 stack_frame_size = -1;
std::vector<LineNumberPair> line_numbers;
std::vector<SubSourceFile> sub_source_files;
bool is_member_function_ish = false; // Filled in by fill_in_pointers_to_member_function_definitions.
Expand Down
7 changes: 6 additions & 1 deletion src/ccc/symbol_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace ccc {

const u32 JSON_FORMAT_VERSION = 13;
const u32 JSON_FORMAT_VERSION = 14;

template <typename SymbolType>
static void write_symbol_list(
Expand Down Expand Up @@ -172,6 +172,11 @@ static void write_json(JsonWriter& json, const Function& symbol, const SymbolDat
json.String(ast::storage_class_to_string(symbol.storage_class));
}

if(symbol.stack_frame_size > -1) {
json.Key("stack_frame_size");
json.Int(symbol.stack_frame_size);
}

if(!symbol.line_numbers.empty()) {
json.Key("line_numbers");
json.StartArray();
Expand Down
25 changes: 22 additions & 3 deletions src/stdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ using namespace ccc;
enum Flags {
NO_FLAGS = 0,
FLAG_SORT_BY_ADDRESS = 1 << 0,
FLAG_LOCAL_SYMBOLS = 1 << 1,
FLAG_PROCEDURE_DESCRIPTORS = 1 << 2,
FLAG_EXTERNAL_SYMBOLS = 1 << 3
FLAG_CALLER_STACK_OFFSETS = 1 << 1,
FLAG_LOCAL_SYMBOLS = 1 << 2,
FLAG_PROCEDURE_DESCRIPTORS = 1 << 3,
FLAG_EXTERNAL_SYMBOLS = 1 << 4
};

struct Options {
Expand Down Expand Up @@ -216,6 +217,8 @@ static void print_functions(FILE* out, const Options& options)
}

CppPrinterConfig config;
config.caller_stack_offsets = options.flags & FLAG_CALLER_STACK_OFFSETS;

CppPrinter printer(out, config);

bool first_iteration = true;
Expand Down Expand Up @@ -254,6 +257,8 @@ static void print_globals(FILE* out, const Options& options)
}

CppPrinterConfig config;
config.caller_stack_offsets = options.flags & FLAG_CALLER_STACK_OFFSETS;

CppPrinter printer(out, config);

bool first_iteration = true;
Expand Down Expand Up @@ -290,6 +295,8 @@ static void print_types(FILE* out, const Options& options)
static void print_types_deduplicated(FILE* out, SymbolDatabase& database, const Options& options)
{
CppPrinterConfig config;
config.caller_stack_offsets = options.flags & FLAG_CALLER_STACK_OFFSETS;

CppPrinter printer(out, config);
printer.comment_block_beginning(options.input_file.filename().string().c_str(), "stdump", get_version());
printer.comment_block_toolchain_version_info(database);
Expand All @@ -302,6 +309,8 @@ static void print_types_deduplicated(FILE* out, SymbolDatabase& database, const
static void print_types_per_file(FILE* out, SymbolDatabase& database, const Options& options)
{
CppPrinterConfig config;
config.caller_stack_offsets = options.flags & FLAG_CALLER_STACK_OFFSETS;

CppPrinter printer(out, config);
printer.comment_block_beginning(options.input_file.filename().string().c_str(), "stdump", get_version());

Expand Down Expand Up @@ -501,6 +510,8 @@ static Options parse_command_line_arguments(int argc, char** argv)
options.importer_flags |= importer_flag;
} else if(strcmp(arg, "--sort-by-address") == 0) {
options.flags |= FLAG_SORT_BY_ADDRESS;
} else if(strcmp(arg, "--caller-stack-offsets") == 0) {
options.flags |= FLAG_CALLER_STACK_OFFSETS;
} else if(strcmp(arg, "--locals") == 0) {
options.flags |= FLAG_LOCAL_SYMBOLS;
} else if(strcmp(arg, "--procedures") == 0) {
Expand Down Expand Up @@ -609,6 +620,14 @@ static void print_help(FILE* out)
fprintf(out, "\n");
fprintf(out, " --sort-by-address Sort symbols by their addresses.\n");
fprintf(out, "\n");
fprintf(out, " --caller-stack-offsets Print the offsets of stack variables relative to\n");
fprintf(out, " to value of the stack pointer register in the\n");
fprintf(out, " caller rather than the value of the stack\n");
fprintf(out, " pointer in the current function. These offsets\n");
fprintf(out, " will be printed out as \"0xN(caller sp)\" instead\n");
fprintf(out, " of \"0xN(sp)\". This option does not affect the\n");
fprintf(out, " JSON output.\n");
fprintf(out, "\n");
fprintf(out, "Importer Options:\n");
print_importer_flags_help(out);
printf("\n");
Expand Down
Loading

0 comments on commit f34cfed

Please sign in to comment.