Browse Source

Draft of DWARF expression evaluation

master
A.Olokhtonov 3 years ago
parent
commit
2053673cbe
  1. 1
      .gitignore
  2. 19
      command.c
  3. 17
      common.h
  4. 554
      dwarf.c
  5. 164
      elf_dwarf.h
  6. 8
      main.c
  7. 11
      res/004-scoped-variables.c
  8. 1
      res/Makefile
  9. 34
      util.c

1
.gitignore vendored

@ -3,3 +3,4 @@ build/ @@ -3,3 +3,4 @@ build/
res/001-simple
res/002-compilation-units
res/003-recursion
res/004-scoped-variables

19
command.c

@ -22,7 +22,7 @@ command_step(struct mi_process proc) @@ -22,7 +22,7 @@ command_step(struct mi_process proc)
struct mi_sourcepoint *next_sp;
do {
// TODO: step until source line changes (for active file)
// TODO: step until source line changes !for active file!
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0);
waitpid(proc.pid, 0, 0);
regs = get_process_registers(proc);
@ -40,6 +40,9 @@ command_start(struct mi_process proc) @@ -40,6 +40,9 @@ command_start(struct mi_process proc)
u64 main_address = proc.base_address + proc.main_address;
long saved_instruction = place_breakpoint_at(proc, main_address);
run_until_breakpoint_and_restore(proc, main_address, saved_instruction);
// TODO: restart if already running/paused
// TODO: process state: not running / running / paused
}
static void
@ -52,7 +55,7 @@ command_next(struct mi_process proc) @@ -52,7 +55,7 @@ command_next(struct mi_process proc)
struct mi_sourcepoint *next_sp;
do {
// TODO: step until source line changes (for active file)
// TODO: step until source line changes !for active file!
ptrace(PTRACE_SINGLESTEP, proc.pid, 0, 0);
waitpid(proc.pid, 0, 0);
@ -97,6 +100,13 @@ command_next(struct mi_process proc) @@ -97,6 +100,13 @@ command_next(struct mi_process proc)
print_sourcepoint(proc, comp_unit, next_sp);
}
static void
command_print(struct mi_process proc, char *identifier, int len)
{
u64 location = lookup_identifier_address(proc, identifier, len);
printf("%#lx\n", location);
}
static void
command_list(struct mi_process proc)
{
@ -113,8 +123,7 @@ command_cont(struct mi_process proc) @@ -113,8 +123,7 @@ command_cont(struct mi_process proc)
}
static void
command_stop(struct mi_process proc)
command_kill(struct mi_process proc)
{
kill(proc.pid, SIGINT);
// TODO
kill(proc.pid, SIGKILL);
}

17
common.h

@ -56,6 +56,19 @@ struct mi_sourcefile { @@ -56,6 +56,19 @@ struct mi_sourcefile {
struct mi_buffer file;
};
struct mi_variable {
char *name;
s64 location;
};
struct mi_block {
u64 low_pc;
u64 high_pc;
struct mi_variable variables[4]; // TODO
int var_count;
};
struct mi_compunit {
u64 low_pc;
u64 high_pc;
@ -70,6 +83,9 @@ struct mi_compunit { @@ -70,6 +83,9 @@ struct mi_compunit {
int source_dirs_count;
char *comp_dir;
struct mi_block blocks[4]; // TODO
int block_count;
};
struct mi_debuginfo {
@ -108,3 +124,4 @@ struct mi_registers { @@ -108,3 +124,4 @@ struct mi_registers {
#define NT_PRSTATUS 1
#define DIE(string) do { fprintf(stderr, string); exit(1); } while (0)
#define ABS(v) ((v) < 0 ? -(v) : (v))

554
dwarf.c

@ -146,6 +146,514 @@ abbrev_entry_offset(u8 *file, u64 abbrev_offset, u32 requested_code) @@ -146,6 +146,514 @@ abbrev_entry_offset(u8 *file, u64 abbrev_offset, u32 requested_code)
return(0);
}
static s64
compute_dwarf_expression_value(u8 *at, u32 length)
{
s64 result = 0;
s64 stack[128] = { 0 };
u32 stack_head = 0;
u8 *original_at = at;
enum dwarf_expression_op op;
u32 increment;
while (at - original_at < length) {
op = *at++;
increment = 0;
switch (op) {
case DW_OP_addr: {
u64 address;
memcpy(&address, at, 8);
stack[stack_head++] = address;
increment = 8;
break;
}
case DW_OP_deref: {
u64 address = stack[--stack_head];
s64 value;
memcpy(&value, (void *) address, 8); // TODO: surely not this...
stack[stack_head++] = value;
break;
}
case DW_OP_const1u: {
u8 const_value = *at;
stack[stack_head++] = const_value;
increment = 1;
break;
}
case DW_OP_const1s: {
s8 const_value = *((s8 *) at);
stack[stack_head++] = const_value;
increment = 1;
break;
}
case DW_OP_const2u: {
u16 const_value;
memcpy(&const_value, at, 2);
stack[stack_head++] = const_value;
increment = 2;
break;
}
case DW_OP_const2s: {
s16 const_value;
memcpy(&const_value, at, 2);
stack[stack_head++] = const_value;
increment = 2;
break;
}
case DW_OP_const4u: {
u32 const_value;
memcpy(&const_value, at, 4);
stack[stack_head++] = const_value;
increment = 4;
break;
}
case DW_OP_const4s: {
s32 const_value;
memcpy(&const_value, at, 4);
stack[stack_head++] = const_value;
increment = 4;
break;
}
case DW_OP_const8u: {
u64 const_value;
memcpy(&const_value, at, 8);
stack[stack_head++] = const_value;
increment = 8;
break;
}
case DW_OP_const8s: {
s64 const_value;
memcpy(&const_value, at, 8);
stack[stack_head++] = const_value;
increment = 8;
break;
}
case DW_OP_constu: {
u32 const_value;
increment = decode_leb128(at, &const_value);
stack[stack_head++] = const_value;
break;
}
case DW_OP_consts: {
s32 const_value;
increment = decode_leb128s(at, &const_value);
stack[stack_head++] = const_value;
break;
}
case DW_OP_dup: {
s64 top = stack[stack_head - 1];
stack[stack_head++] = top;
break;
}
case DW_OP_drop: {
--stack_head;
break;
}
case DW_OP_over: {
s64 value = stack[stack_head - 2];
stack[stack_head++] = value;
break;
}
case DW_OP_pick: {
u8 stack_index = *at;
increment = 1;
// NOTE: 0 means top of stack
s64 value = stack[stack_head - 1 - stack_index];
stack[stack_head++] = value;
break;
}
case DW_OP_swap: {
s64 top = stack[stack_head - 1];
s64 second_from_top = stack[stack_head - 2];
stack[stack_head - 2] = top;
stack[stack_head - 1] = second_from_top;
break;
}
case DW_OP_rot: {
s64 top = stack[stack_head - 1];
s64 second = stack[stack_head - 2];
s64 third = stack[stack_head - 3];
stack[stack_head - 1] = second;
stack[stack_head - 2] = third;
stack[stack_head - 3] = top;
break;
}
case DW_OP_xderef: {
/*
TODO: The top two stack elements are popped, and a data item is retrieved through an implementation-defined address calculation and pushed as the new stack top. The size of the data retrieved from the dereferenced address is the size of an address on the target machine.
*/
stack_head -= 2;
s64 value = 0xdeadbeef;
stack[stack_head++] = value;
break;
}
case DW_OP_abs: {
stack[stack_head - 1] = ABS(stack[stack_head - 1]);
break;
}
case DW_OP_and: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b & a;
stack[stack_head++] = result;
break;
}
case DW_OP_div: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b / a;
stack[stack_head++] = result;
break;
}
case DW_OP_minus: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b - a;
stack[stack_head++] = result;
break;
}
case DW_OP_mod: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b % a;
stack[stack_head++] = result;
break;
}
case DW_OP_mul: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b * a;
stack[stack_head++] = result;
break;
}
case DW_OP_neg: {
stack[stack_head - 1] = -stack[stack_head - 1];
break;
}
case DW_OP_not: {
stack[stack_head - 1] = ~stack[stack_head - 1];
break;
}
case DW_OP_or: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b | a;
stack[stack_head++] = result;
break;
}
case DW_OP_plus: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b + a;
stack[stack_head++] = result;
break;
}
case DW_OP_plus_uconst: {
u32 const_value;
increment = decode_leb128(at, &const_value);
s64 a = stack[--stack_head];
s64 result = a + const_value;
stack[stack_head++] = result;
break;
}
case DW_OP_shl: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b << a;
stack[stack_head++] = result;
break;
}
case DW_OP_shr: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b >> a;
stack[stack_head++] = result;
break;
}
case DW_OP_shra: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result;
if (b > 0) {
result = b >> a;
} else {
result = ~(~b >> a);
}
stack[stack_head++] = result;
break;
}
case DW_OP_xor: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
s64 result = b ^ a;
stack[stack_head++] = result;
break;
break;
}
case DW_OP_skip: {
s16 const_value;
memcpy(&const_value, at, 2);
increment = 2;
increment += const_value;
break;
}
case DW_OP_bra: {
s16 const_value;
memcpy(&const_value, at, 2);
increment = 2;
s64 top = stack[--stack_head];
if (top) {
increment += const_value;
}
break;
}
case DW_OP_eq: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b == a ? 1 : 0);
break;
}
case DW_OP_ge: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b >= a ? 1 : 0);
break;
}
case DW_OP_gt: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b > a ? 1 : 0);
break;
}
case DW_OP_le: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b <= a ? 1 : 0);
break;
}
case DW_OP_lt: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b < a ? 1 : 0);
break;
}
case DW_OP_ne: {
s64 a = stack[--stack_head];
s64 b = stack[--stack_head];
stack[stack_head++] = (b != a ? 1 : 0);
break;
}
case DW_OP_lit0 ... DW_OP_lit31: {
u32 value = op - DW_OP_lit0;
stack[stack_head++] = value;
break;
}
case DW_OP_reg0 ... DW_OP_reg31: {
break;
}
case DW_OP_breg0 ... DW_OP_breg31: {
s32 offset;
increment = decode_leb128s(at, &offset);
break;
}
case DW_OP_regx: {
u32 reg;
increment = decode_leb128(at, &reg);
break;
}
case DW_OP_fbreg: {
s32 offset;
increment = decode_leb128s(at, &offset);
stack[stack_head++] = offset;
break;
}
case DW_OP_bregx: {
u32 reg;
s32 offset;
increment = decode_leb128(at, &reg);
increment += decode_leb128s(at, &offset);
break;
}
case DW_OP_piece: {
u32 size;
increment = decode_leb128(at, &size);
break;
}
case DW_OP_deref_size: {
u8 size = *at;
increment = 1;
u64 address = stack[--stack_head];
s64 value;
memcpy(&value, (void *) address, size); // TODO: surely not this..
stack[stack_head++] = value;
break;
}
case DW_OP_xderef_size: {
u8 size = *at;
increment = 1;
/*
TODO: The top two stack elements are popped, and a data item is retrieved through an implementation-defined address calculation and pushed as the new stack top. The size of the data retrieved from the dereferenced address is the size of an address on the target machine.
*/
stack_head -= 2;
s64 value = 0xdeadbeef;
stack[stack_head++] = value;
break;
}
case DW_OP_nop: {
break;
}
case DW_OP_push_object_address: {
/*
TODO: The DW_OP_push_object_address operation pushes the address of the object currently being evaluated as part of evaluation of a user presented expression. This object may correspond to an independent variable described by its own debugging information entry or it may be a component of an array, structure, or class whose address has been dynamically determined by an earlier step during user expression evaluation.
*/
s64 value = 0xdeadbeef;
stack[stack_head++] = value;
break;
}
case DW_OP_call2: {
u16 offset;
memcpy(&offset, at, 2);
increment = 2;
DIE("i can't call2\n");
break;
}
case DW_OP_call4: {
u32 offset;
memcpy(&offset, at, 4);
increment = 4;
DIE("i can't call4\n");
break;
}
case DW_OP_call_ref: {
u32 offset; // u64 on 64-bit dwarf !
memcpy(&offset, at, 4);
increment = 4;
DIE("i can't call_ref\n");
break;
}
case DW_OP_form_tls_address: {
/*
TODO: The DW_OP_form_tls_address operation pops a value from the stack, translates it into an address in the current thread's thread-local storage block, and pushes the address. If the DWARF expression containing the DW_OP_form_tls_address operation belongs to the main executable's DWARF info, the operation uses the main executable's thread-local storage block; if the expression belongs to a shared library's DWARF info, then it uses that shared library's thread-local storage block.
*/
s64 top = stack[--stack_head];
s64 value = 0xdeadbeef;
stack[stack_head++] = value;
break;
}
case DW_OP_call_frame_cfa: {
s64 address = 0xdeadbeef; // TODO: get CFA address
stack[stack_head++] = address;
break;
}
case DW_OP_bit_piece: {
u32 size;
u32 offset;
increment = decode_leb128(at, &size);
increment += decode_leb128(at, &offset);
break;
}
case DW_OP_implicit_value: {
u32 size;
increment = decode_leb128(at, &size);
increment += size;
break;
}
case DW_OP_stack_value: {
break;
}
case DW_OP_lo_user: {
break;
}
case DW_OP_hi_user: {
break;
}
default: {
printf("unknown dwarf op %d\n", op);
}
}
at += increment;
}
result = stack[stack_head - 1];
return(result);
}
static u32
read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u64 base_data_offset, u32 form, u64 data_offset, u64 *value)
{
@ -189,10 +697,12 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u64 base_d @@ -189,10 +697,12 @@ read_actual_debug_data(u8 *file, u64 string_offset, u32 address_size, u64 base_d
}
case DW_FORM_exprloc: {
// TODO: return value to caller
u32 length;
increment = decode_leb128(file + data_offset, &length);
s64 expression_value = compute_dwarf_expression_value(file + data_offset + increment, length);
*value = expression_value;
increment += length;
break;
@ -262,11 +772,26 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -262,11 +772,26 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
struct mi_function *func = dest->functions + dest->func_count;
struct mi_compunit *comp_unit = dest->compilation_units + dest->cu_count;
struct mi_block *block = comp_unit->blocks;
struct mi_variable *variable = block->variables;
enum dwarf_die_tag parent = 0;
// TODO: make this not bad
for (;;) {
data_offset += decode_leb128(file + data_offset, &code);
if (code == 0) {
// NOTE: finalize parent
if (parent == DW_TAG_lexical_block) {
block->high_pc = block->low_pc + block->high_pc;
++block;
++comp_unit->block_count;
variable = block->variables;
__builtin_trap();
}
if (depth > 1) {
--depth;
continue;
@ -283,6 +808,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -283,6 +808,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
u32 has_children = file[schema_offset++];
if (has_children) {
parent = tag;
++depth;
}
@ -312,16 +838,27 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -312,16 +838,27 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
} else if (attribute == DW_AT_high_pc) {
func->high_pc = value;
}
} else if (tag == DW_TAG_lexical_block) {
if (attribute == DW_AT_low_pc) {
block->low_pc = value;
} else if (attribute == DW_AT_high_pc) {
block->high_pc = value;
}
} else if (tag == DW_TAG_variable) {
if (attribute == DW_AT_name) {
variable->name = (char *) value;
} else if (attribute == DW_AT_location) {
variable->location = value;
}
}
} while (attribute != 0 || form != 0);
if (tag == DW_TAG_compile_unit) {
comp_unit->high_pc = comp_unit->low_pc + comp_unit->high_pc;
++comp_unit;
++dest->cu_count;
if (parent == DW_TAG_variable) {
++variable;
++block->var_count;
}
if (tag == DW_TAG_subprogram) {
if (parent == DW_TAG_subprogram) {
func->high_pc = func->low_pc + func->high_pc;
func->comp_unit = dest->cu_count;
++func;
@ -329,6 +866,9 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -329,6 +866,9 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
}
}
comp_unit->high_pc = comp_unit->low_pc + comp_unit->high_pc;
++dest->cu_count;
return(di_header.length + 4);
}

164
elf_dwarf.h

@ -314,6 +314,170 @@ enum dwarf_lnp_opcode_extended { @@ -314,6 +314,170 @@ enum dwarf_lnp_opcode_extended {
DW_LNE_set_discriminator = 0x04,
};
enum dwarf_expression_op {
DW_OP_addr = 0x03,
DW_OP_deref = 0x06,
DW_OP_const1u = 0x08,
DW_OP_const1s = 0x09,
DW_OP_const2u = 0x0a,
DW_OP_const2s = 0x0b,
DW_OP_const4u = 0x0c,
DW_OP_const4s = 0x0d,
DW_OP_const8u = 0x0e,
DW_OP_const8s = 0x0f,
DW_OP_constu = 0x10,
DW_OP_consts = 0x11,
DW_OP_dup = 0x12,
DW_OP_drop = 0x13,
DW_OP_over = 0x14,
DW_OP_pick = 0x15,
DW_OP_swap = 0x16,
DW_OP_rot = 0x17,
DW_OP_xderef = 0x18,
DW_OP_abs = 0x19,
DW_OP_and = 0x1a,
DW_OP_div = 0x1b,
DW_OP_minus = 0x1c,
DW_OP_mod = 0x1d,
DW_OP_mul = 0x1e,
DW_OP_neg = 0x1f,
DW_OP_not = 0x20,
DW_OP_or = 0x21,
DW_OP_plus = 0x22,
DW_OP_plus_uconst = 0x23,
DW_OP_shl = 0x24,
DW_OP_shr = 0x25,
DW_OP_shra = 0x26,
DW_OP_xor = 0x27,
DW_OP_skip = 0x2f,
DW_OP_bra = 0x28,
DW_OP_eq = 0x29,
DW_OP_ge = 0x2a,
DW_OP_gt = 0x2b,
DW_OP_le = 0x2c,
DW_OP_lt = 0x2d,
DW_OP_ne = 0x2e,
DW_OP_lit0 = 0x30,
DW_OP_lit1 = 0x31,
DW_OP_lit2 = 0x32,
DW_OP_lit3 = 0x33,
DW_OP_lit4 = 0x34,
DW_OP_lit5 = 0x35,
DW_OP_lit6 = 0x36,
DW_OP_lit7 = 0x37,
DW_OP_lit8 = 0x38,
DW_OP_lit9 = 0x39,
DW_OP_lit10 = 0x3a,
DW_OP_lit11 = 0x3b,
DW_OP_lit12 = 0x3c,
DW_OP_lit13 = 0x3d,
DW_OP_lit14 = 0x3e,
DW_OP_lit15 = 0x3f,
DW_OP_lit16 = 0x40,
DW_OP_lit17 = 0x41,
DW_OP_lit18 = 0x42,
DW_OP_lit19 = 0x43,
DW_OP_lit20 = 0x44,
DW_OP_lit21 = 0x45,
DW_OP_lit22 = 0x46,
DW_OP_lit23 = 0x47,
DW_OP_lit24 = 0x48,
DW_OP_lit25 = 0x49,
DW_OP_lit26 = 0x4a,
DW_OP_lit27 = 0x4b,
DW_OP_lit28 = 0x4c,
DW_OP_lit29 = 0x4d,
DW_OP_lit30 = 0x4e,
DW_OP_lit31 = 0x4f,
DW_OP_reg0 = 0x50,
DW_OP_reg1 = 0x51,
DW_OP_reg2 = 0x52,
DW_OP_reg3 = 0x53,
DW_OP_reg4 = 0x54,
DW_OP_reg5 = 0x55,
DW_OP_reg6 = 0x56,
DW_OP_reg7 = 0x57,
DW_OP_reg8 = 0x58,
DW_OP_reg9 = 0x59,
DW_OP_reg10 = 0x5a,
DW_OP_reg11 = 0x5b,
DW_OP_reg12 = 0x5c,
DW_OP_reg13 = 0x5d,
DW_OP_reg14 = 0x5e,
DW_OP_reg15 = 0x5f,
DW_OP_reg16 = 0x60,
DW_OP_reg17 = 0x61,
DW_OP_reg18 = 0x62,
DW_OP_reg19 = 0x63,
DW_OP_reg20 = 0x64,
DW_OP_reg21 = 0x65,
DW_OP_reg22 = 0x66,
DW_OP_reg23 = 0x67,
DW_OP_reg24 = 0x68,
DW_OP_reg25 = 0x69,
DW_OP_reg26 = 0x6a,
DW_OP_reg27 = 0x6b,
DW_OP_reg28 = 0x6c,
DW_OP_reg29 = 0x6d,
DW_OP_reg30 = 0x6e,
DW_OP_reg31 = 0x6f,
DW_OP_breg0 = 0x70,
DW_OP_breg1 = 0x71,
DW_OP_breg2 = 0x72,
DW_OP_breg3 = 0x73,
DW_OP_breg4 = 0x74,
DW_OP_breg5 = 0x75,
DW_OP_breg6 = 0x76,
DW_OP_breg7 = 0x77,
DW_OP_breg8 = 0x78,
DW_OP_breg9 = 0x79,
DW_OP_breg10 = 0x7a,
DW_OP_breg11 = 0x7b,
DW_OP_breg12 = 0x7c,
DW_OP_breg13 = 0x7d,
DW_OP_breg14 = 0x7e,
DW_OP_breg15 = 0x7f,
DW_OP_breg16 = 0x80,
DW_OP_breg17 = 0x81,
DW_OP_breg18 = 0x82,
DW_OP_breg19 = 0x83,
DW_OP_breg20 = 0x84,
DW_OP_breg21 = 0x85,
DW_OP_breg22 = 0x86,
DW_OP_breg23 = 0x87,
DW_OP_breg24 = 0x88,
DW_OP_breg25 = 0x89,
DW_OP_breg26 = 0x8a,
DW_OP_breg27 = 0x8b,
DW_OP_breg28 = 0x8c,
DW_OP_breg29 = 0x8d,
DW_OP_breg30 = 0x8e,
DW_OP_breg31 = 0x8f,
DW_OP_regx = 0x90,
DW_OP_fbreg = 0x91,
DW_OP_bregx = 0x92,
DW_OP_piece = 0x93,
DW_OP_deref_size = 0x94,
DW_OP_xderef_size = 0x95,
DW_OP_nop = 0x96,
DW_OP_push_object_address = 0x97,
DW_OP_call2 = 0x98,
DW_OP_call4 = 0x99,
DW_OP_call_ref = 0x9a,
DW_OP_form_tls_address = 0x9b,
DW_OP_call_frame_cfa = 0x9c,
DW_OP_bit_piece = 0x9d,
DW_OP_implicit_value = 0x9e,
DW_OP_stack_value = 0x9f,
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff
};
#pragma pack(1)
struct elf_header_x64 {
char magic[4];

8
main.c

@ -49,6 +49,8 @@ main(int argc, char *argv[]) @@ -49,6 +49,8 @@ main(int argc, char *argv[])
command_step(process);
} else if (0 == strncmp(command, "start\n", command_length)) {
command_start(process);
} else if (0 == strncmp(command, "print ", 6)) {
command_print(process, command + 6, command_length - 7);
} else if (0 == strncmp(command, "next\n", command_length)) {
command_next(process);
} else if (0 == strncmp(command, "line\n", command_length)) {
@ -56,11 +58,11 @@ main(int argc, char *argv[]) @@ -56,11 +58,11 @@ main(int argc, char *argv[])
} else if (0 == strncmp(command, "cont\n", command_length)) {
command_cont(process);
wait = 1;
} else if (0 == strncmp(command, "stop\n", command_length)) {
command_stop(process);
} else if (0 == strncmp(command, "kill\n", command_length)) {
command_kill(process);
wait = 1;
} else {
printf("Unknown command: %*s", command_length, command);
printf("Unknown command: %.*s", command_length, command);
}
if (wait) {

11
res/004-scoped-variables.c

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
int
main(int argc, char **argv)
{
int outer = 1;
if (outer > 0) {
char *inner = "INNER";
int outer = -1;
outer += 10;
}
return(0);
}

1
res/Makefile

@ -2,3 +2,4 @@ all: @@ -2,3 +2,4 @@ all:
gcc -g -o 001-simple 001-simple.c
gcc -g -o 002-compilation-units 002-compilation-units.c 002-compilation-units-impl.c
gcc -g -o 003-recursion 003-recursion.c
gcc -g -o 004-scoped-variables 004-scoped-variables.c

34
util.c

@ -121,6 +121,7 @@ pc_to_sourcepoint(struct mi_process proc, u64 pc, int *comp_unit) @@ -121,6 +121,7 @@ pc_to_sourcepoint(struct mi_process proc, u64 pc, int *comp_unit)
return(unit.sp_table + i - 1);
}
}
break;
}
}
@ -271,4 +272,37 @@ print_current_instruction(struct mi_process proc) @@ -271,4 +272,37 @@ print_current_instruction(struct mi_process proc)
printf("PC = %#018lx: %x %x %x %x [%x] %x %x %x %x %x %x %x\n", regs.rip,
nb[0], nb[1], nb[2], nb[3], nb[4], nb[5], nb[6], nb[7],
nb[8], nb[9], nb[10], nb[11]);
}
static u64
lookup_identifier_address(struct mi_process proc, char *ident, int len)
{
struct mi_registers regs = get_process_registers(proc);
u64 pc_local = regs.rip - proc.base_address;
for (int c = 0; c < proc.debug.cu_count; ++c) {
struct mi_compunit unit = proc.debug.compilation_units[c];
if (unit.low_pc <= pc_local && pc_local < unit.high_pc) {
for (int b = 0; b < unit.block_count; ++b) {
struct mi_block block = unit.blocks[b];
if (block.low_pc <= pc_local && pc_local < block.high_pc) {
for (int v = 0; v < block.var_count; ++v) {
struct mi_variable variable = block.variables[v];
if (0 == strncmp(variable.name, ident, len)) {
return(variable.location);
}
}
break;
}
}
break;
}
}
return(0);
}
Loading…
Cancel
Save