Skip to content

Commit

Permalink
Teach the BEAM loader to load debug information
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorng committed Sep 3, 2024
1 parent 9892217 commit 715cd95
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 1 deletion.
151 changes: 151 additions & 0 deletions erts/emulator/beam/beam_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,148 @@ static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) {
}
}

static int parse_debug_chunk_data(BeamFile *beam, BeamReader *p_reader) {
Sint32 count;
Sint32 num_vars;
int i;
BeamOpAllocator op_allocator;
BeamCodeReader *op_reader;
BeamOp* op = NULL;

LoadAssert(beamreader_read_i32(p_reader, &count));
LoadAssert(beamreader_read_i32(p_reader, &num_vars));

erts_printf("DbgB: %T: %d %d\n", beam->module, count, num_vars);

beamopallocator_init(&op_allocator);

op_reader = erts_alloc(ERTS_ALC_T_PREPARED_CODE, sizeof(BeamCodeReader));

op_reader->allocator = &op_allocator;
op_reader->file = beam;
op_reader->pending = NULL;
op_reader->first = 1;
op_reader->reader = *p_reader;

for (i = 0; i < count; i++) {
BeamOpArg *arg;
int extra_args;

if (!beamcodereader_next(op_reader, &op)) {
goto error;
}
if (op->op != genop_call_2) {
goto error;
}

arg = op->a;

switch (arg->type) {
case TAG_n:
erts_printf("%d: no stack frame\n", i + 1);
break;
case TAG_u:
erts_printf("%d: %u\n", i + 1, op->a[0].val);
break;
default:
goto error;
}

arg++;

if (arg->type != TAG_u) {
goto error;
}
extra_args = arg->val;

arg++;

while (extra_args > 0) {
Eterm var_name;
byte *base;
Uint offset;
Uint size;

if (arg[0].type != TAG_q) {
goto error;
}

var_name = beamfile_get_literal(beam, arg[0].val);
if (!is_bitstring(var_name)) {
goto error;
}
ERTS_GET_BITSTRING(var_name, base, offset, size);
if (offset != 0 || size % 8 != 0) {
goto error;
}

erts_printf(" %.*s ", size / 8, base);

switch (arg[1].type) {
case TAG_i:
erts_printf("%ld", arg[1].val);
break;
case TAG_a:
erts_printf("%T", arg[1].val);
break;
case TAG_x:
erts_printf("{x,%ld}", arg[1].val);
break;
case TAG_y:
erts_printf("{y,%ld}", arg[1].val);
break;
case TAG_q:
erts_printf("%T", beamfile_get_literal(beam, arg[1].val));
break;
default:
goto error;
}

erts_printf("\n");

arg += 2;
extra_args -= 2;
}

if (extra_args < 0) {
goto error;
}

erts_printf("\n");

beamopallocator_free_op(&op_allocator, op);
}

beamcodereader_close(op_reader);
beamopallocator_dtor(&op_allocator);

return 1;

error:
if (op != NULL) {
beamopallocator_free_op(&op_allocator, op);
}
beamcodereader_close(op_reader);
beamopallocator_dtor(&op_allocator);
return 0;
}

static int parse_debug_chunk(BeamFile *beam, IFF_Chunk *chunk) {
BeamReader reader;
Sint32 version;

beamreader_init(chunk->data, chunk->size, &reader);

LoadAssert(beamreader_read_i32(&reader, &version));

if (version == 0) {
return parse_debug_chunk_data(beam, &reader);
} else {
/* Silently ignore chunk of wrong version. */
return 1;
}
}

static ErlHeapFragment *new_literal_fragment(Uint size)
{
ErlHeapFragment *bp;
Expand Down Expand Up @@ -898,6 +1040,7 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
MakeIffId('A', 't', 'o', 'm'), /* 11 */
MakeIffId('T', 'y', 'p', 'e'), /* 12 */
MakeIffId('M', 'e', 't', 'a'), /* 13 */
MakeIffId('D', 'b', 'g', 'B'), /* 14 */
};

static const int UTF8_ATOM_CHUNK = 0;
Expand All @@ -916,6 +1059,7 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
static const int OBSOLETE_ATOM_CHUNK = 11;
static const int TYPE_CHUNK = 12;
static const int META_CHUNK = 13;
static const int DEBUG_CHUNK = 14;

static const int NUM_CHUNKS = sizeof(chunk_iffs) / sizeof(chunk_iffs[0]);

Expand Down Expand Up @@ -1013,6 +1157,13 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
init_fallback_type_table(beam);
}

if (chunks[DEBUG_CHUNK].size > 0) {
if (!parse_debug_chunk(beam, &chunks[DEBUG_CHUNK])) {
error = BEAMFILE_READ_CORRUPT_DEBUG_TABLE;
goto error;
}
}

beam->strings.data = chunks[STR_CHUNK].data;
beam->strings.size = chunks[STR_CHUNK].size;

Expand Down
3 changes: 2 additions & 1 deletion erts/emulator/beam/beam_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ enum beamfile_read_result {
BEAMFILE_READ_CORRUPT_LAMBDA_TABLE,
BEAMFILE_READ_CORRUPT_LINE_TABLE,
BEAMFILE_READ_CORRUPT_LITERAL_TABLE,
BEAMFILE_READ_CORRUPT_TYPE_TABLE
BEAMFILE_READ_CORRUPT_TYPE_TABLE,
BEAMFILE_READ_CORRUPT_DEBUG_TABLE
};

typedef struct {
Expand Down
2 changes: 2 additions & 0 deletions erts/emulator/beam/beam_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
BeamLoadError0(stp, "corrupt locals table");
case BEAMFILE_READ_CORRUPT_TYPE_TABLE:
BeamLoadError0(stp, "corrupt type table");
case BEAMFILE_READ_CORRUPT_DEBUG_TABLE:
BeamLoadError0(stp, "corrupt BEAM debug information table");
case BEAMFILE_READ_SUCCESS:
break;
}
Expand Down

0 comments on commit 715cd95

Please sign in to comment.