Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for debug information for a native debugger #9334

Merged
merged 5 commits into from
Feb 3, 2025
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: 6 additions & 3 deletions erts/emulator/beam/atom.names
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ atom asynchronous
atom atom
atom atom_used
atom attributes
atom auto
atom auto_connect
atom await_exit
atom await_microstate_accounting_modifications
Expand Down Expand Up @@ -217,6 +218,7 @@ atom debug_flags
atom decentralized_counters
atom decimals
atom default
atom debug_hash_fixed_number_of_locks
atom delay_trap
atom demonitor
atom deterministic
Expand Down Expand Up @@ -260,6 +262,7 @@ atom emulator
atom enable_trace
atom enabled
atom endian
atom entry
atom env
atom ensure_at_least ensure_exactly
atom eof
Expand Down Expand Up @@ -486,6 +489,7 @@ atom new_processes
atom new_ports
atom new_uniq
atom newline
atom nifs
atom no
atom nomatch
atom none
Expand Down Expand Up @@ -768,10 +772,9 @@ atom warning
atom warning_msg
atom wordsize
atom write_concurrency
atom x
atom xor
atom x86
atom y
atom yes
atom yield
atom nifs
atom auto
atom debug_hash_fixed_number_of_locks
132 changes: 132 additions & 0 deletions erts/emulator/beam/beam_bif_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,138 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
return 0;
}

BIF_RETTYPE code_get_debug_info_1(BIF_ALIST_1)
{
#ifdef BEAMASM
ErtsCodeIndex code_ix;
Module* modp;
const BeamCodeHeader* hdr;
const BeamCodeLineTab* lt;
const BeamDebugTab* debug;
Sint i;
Uint alloc_size;
Eterm result = NIL;
Eterm* hp;
Eterm* hend;

if (is_not_atom(BIF_ARG_1)) {
BIF_ERROR(BIF_P, BADARG);
}
code_ix = erts_active_code_ix();
modp = erts_get_module(BIF_ARG_1, code_ix);
if (modp == NULL) {
BIF_ERROR(BIF_P, BADARG);
}
hdr = modp->curr.code_hdr;
if (hdr == NULL) {
BIF_ERROR(BIF_P, BADARG);
}

lt = hdr->line_table;

debug = hdr->debug;
if (debug == NULL) {
return am_none;
}

alloc_size = 0;

for (i = 0; i < debug->item_count; i++) {
/* [ {Line, {FrameSize, Pairs}} ] */
alloc_size += 2 + 3 + 3;
/* Pairs = [{Name, Value}], where Value is an atom or 2-tuple.
*
* Assume they are all 2-tuples and HRelease() the excess
* later. */
alloc_size += debug->items[i].num_vars * (2 + 3 + 3);
}

hp = HAlloc(BIF_P, alloc_size);
hend = hp + alloc_size;

for (i = debug->item_count-1; i >= 0; i--) {
BeamDebugItem* items = &debug->items[i];
Sint frame_size = items->frame_size;
Uint num_vars = items->num_vars;
Eterm *tp = &items->first[2 * (num_vars - 1)];
Uint32 location_index, location;
Eterm frame_size_term;
Eterm var_list = NIL;
Eterm tmp;

location_index = items->location_index;

if (location_index == ERTS_UINT32_MAX) {
continue;
}
if (lt->loc_size == 2) {
location = lt->loc_tab.p2[location_index];
} else {
ASSERT(lt->loc_size == 4);
location = lt->loc_tab.p4[location_index];
}

switch (frame_size) {
case BEAMFILE_FRAMESIZE_ENTRY:
frame_size_term = am_entry;
break;
case BEAMFILE_FRAMESIZE_NONE:
frame_size_term = am_none;
break;
default:
ASSERT(frame_size >= 0);
frame_size_term = make_small(frame_size);
jhogberg marked this conversation as resolved.
Show resolved Hide resolved
break;
}

while (num_vars-- != 0) {
Eterm val;
Eterm tag;

switch(loader_tag(tp[1])) {
case LOADER_X_REG:
tag = am_x;
val = make_small(loader_x_reg_index(tp[1]));
break;
case LOADER_Y_REG:
tag = am_y;
val = make_small(loader_y_reg_index(tp[1]));
break;
default:
tag = am_value;
val = tp[1];
break;
}
tmp = TUPLE2(hp, tag, val);
hp += 3;

tmp = TUPLE2(hp, tp[0], tmp);
hp += 3;

tp -= 2;

var_list = CONS(hp, tmp, var_list);
hp += 2;
}

tmp = TUPLE2(hp, frame_size_term, var_list);
hp += 3;

tmp = TUPLE2(hp, make_small(LOC_LINE(location)), tmp);
hp += 3;

result = CONS(hp, tmp, result);
hp += 2;
}

ASSERT(hp <= hend);
HRelease(BIF_P, hend, hp);
return result;
#endif

BIF_ERROR(BIF_P, BADARG);
}

/*
* Release of literal areas...
*
Expand Down
21 changes: 21 additions & 0 deletions erts/emulator/beam/beam_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#define MD5_SIZE MD5_DIGEST_LENGTH

typedef struct BeamCodeLineTab_ BeamCodeLineTab;
typedef struct BeamDebugTab_ BeamDebugTab;

/*
* Header of code chunks which contains additional information
Expand Down Expand Up @@ -99,6 +100,11 @@ typedef struct beam_code_header {
Uint32 *loc_index_to_cover_id;
Uint line_coverage_len;

/*
* Debug information. debug->items are indexed directly by
* the index in each `debug_line` instruction.
*/
const BeamDebugTab *debug;
#endif

/*
Expand Down Expand Up @@ -137,6 +143,21 @@ struct BeamCodeLineTab_ {
const void** func_tab[1];
};

/*
* Layout of the debug information.
*/
typedef struct {
Uint32 location_index;
Sint16 frame_size;
Uint16 num_vars;
Eterm *first;
} BeamDebugItem;

struct BeamDebugTab_ {
Uint32 item_count;
BeamDebugItem *items;
};

/* Total code size in bytes */
extern Uint erts_total_code_size;

Expand Down
Loading
Loading