Class: RDwarf

Inherits:
Object
  • Object
show all
Defined in:
lib/rdwarf.rb,
ext/rdwarf/rdwarf.c

Defined Under Namespace

Modules: Attribute, DIE Classes: Error, LocationDescriptor, LocationList

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'ext/rdwarf/rdwarf.c', line 268

static VALUE rdwarf_initialize(VALUE self, VALUE filename)
{
    rdwarf_t *rd = GetRDwarf(self);
    Elf *elf;
    Dwarf_Debug dbg;
    Dwarf_Error err;
    int fd;
    int ret;

    SafeStringValue(filename);
    filename = rb_str_export_to_enc(filename, rb_filesystem_encoding());

    fd = rb_cloexec_open(StringValueCStr(filename), O_RDONLY, 0);
    if (fd < 0) {
        rb_sys_fail("open");
    }
    elf = elf_begin(fd, ELF_C_READ, (Elf*)0);
    ret = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
    if (ret == DW_DLV_NO_ENTRY) {
        elf_end(elf);
        rb_raise(rd_eError, "%s", dwarf_errmsg(err));
    }
    rd->shared_data = rd_shared_data_alloc(elf, dbg, self);
    return self;
}

Instance Method Details

#compile_unitsObject



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'ext/rdwarf/rdwarf.c', line 294

static VALUE rdwarf_compile_units(VALUE self)
{
    rdwarf_t *rd = GetRDwarf(self);
    Dwarf_Unsigned cu_header_length = 0;
    Dwarf_Unsigned abbrev_offset = 0;
    Dwarf_Half version_stamp = 0;
    Dwarf_Half address_size = 0;
    Dwarf_Unsigned next_cu_offset = 0;
    Dwarf_Error err;
    Dwarf_Die die;
    VALUE ary;

    if (rd->compile_units != Qfalse) {
      return rd->compile_units;
    }
    ary = rb_ary_new();

    while (dwarf_next_cu_header(rd->shared_data->dbg, &cu_header_length, &version_stamp, &abbrev_offset,
                                &address_size, &next_cu_offset, &err) == DW_DLV_OK) {
        if (!chkerr2(dwarf_siblingof(rd->shared_data->dbg, NULL, &die, &err), &err)) {
            continue;
        }
        rb_ary_push(ary, rd_die_new(rd->shared_data, self, Qnil, die));
    }
    rd->compile_units = ary;
    return ary;
}

#die_at(offset) ⇒ Object



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'ext/rdwarf/rdwarf.c', line 322

static VALUE rdwarf_die_at(VALUE self, VALUE offset)
{
    rdwarf_t *rd = GetRDwarf(self);
    Dwarf_Die die;
    Dwarf_Off cu_off;
    Dwarf_Error err;
    VALUE cu;

    chkerr1(dwarf_offdie(rd->shared_data->dbg, NUM2LL(offset), &die, &err), &err, self);
    chkerr1(dwarf_CU_dieoffset_given_die(die, &cu_off, &err), &err, self);

    rdwarf_compile_units(self);
    cu = rb_hash_aref(rd->shared_data->off2die, LL2NUM(cu_off));
    if (NIL_P(cu)) {
        rb_raise(rd_eError, "Cannot find CU");
    }
    return rd_die_new(rd->shared_data, self, cu, die);
}

#dumpObject



51
52
53
54
55
56
57
# File 'lib/rdwarf.rb', line 51

def dump
  s = []
  compile_units.each do |cu|
    s << cu.dump
  end
  s.join("\n")
end

#offsetof(type_name, member_name) ⇒ Object

Find an offset of a structure.

# On Ubuntu 12.04 x86_64 with libc6-dbg package
rd = RDwarf.new('/usr/lib/debug/lib/x86_64-linux-gnu/libc-2.15.so')
rd.offsetof('struct timeval', 'tv_usec') # => 8


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rdwarf.rb', line 11

def offsetof(type_name, member_name)
  if type_name =~ /^struct\s+/
    die_type = DIE::StructureType
    type_name = $'
  else
    die_type = DIE::Typedef
  end

  die = compile_units.find do |cu|
    die = cu.children.find do |die|
      break die if die.is_a? die_type and die.name == type_name
    end
    break die if die
  end

  while die
    case die
    when DIE::Typedef
      die = die.attributes.find do |attr|
        if attr.is_a? Attribute::Type
          break attr.value
        end
      end
    when DIE::StructureType
      die.children.find do |die|
        if die.name == member_name
          die.attributes.find do |attr|
            if attr.is_a? Attribute::DataMemberLocation
              return attr.value
            end
          end
        end
      end
      return nil
    else
      return nil # never reach here
    end
  end
end