Module: ElfUtils::Types::ULEB128 Private

Extended by:
CTypes::Type
Defined in:
lib/elf_utils/types/uleb128.rb,
ext/elf_utils/elf_utils.c

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Class Method Summary collapse

Class Method Details

.fixed_size?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


17
18
19
# File 'lib/elf_utils/types/uleb128.rb', line 17

def self.fixed_size?
  false
end

.greedy?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


25
26
27
# File 'lib/elf_utils/types/uleb128.rb', line 25

def self.greedy?
  false
end

.pack(value, endian: default_endian, validate: true) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

provide a method for packing the ruby value into the binary representation



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/elf_utils/types/uleb128.rb', line 30

def self.pack(value, endian: default_endian, validate: true)
  return "\0" if value == 0
  buf = +""
  while value != 0
    byte = (value & 0x7f)
    value >>= 7
    byte |= 0x80 if value != 0
    buf << byte
  end
  buf
end

.sizeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



21
22
23
# File 'lib/elf_utils/types/uleb128.rb', line 21

def self.size
  @size
end

.unpack_one(*args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Define the class method (static function) in the class



8
9
10
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
# File 'ext/elf_utils/elf_utils.c', line 8

static VALUE
uleb128_unpack_one(int argc, VALUE *argv, VALUE self)
{
    if (argc < 1) {
        rb_raise(rb_eArgError,
            "wrong number of arguments (given %d, expected at least 1)", argc);
    }

    char *buf       = StringValuePtr(argv[0]);
    size_t len      = rb_str_length(argv[0]);
    size_t offset   = 0;
    uint64_t result = 0; // ran into conversion issues when using 128bit
    int shift       = 0;

    while (offset < len) {
        uint8_t byte = *(buf + offset++);
        result |= (uint64_t)(byte & 0x7F) << shift;

        // If the MSB is not set, we're done
        if ((byte & 0x80) == 0) {
            // not returning a bigint here because the dry-types enum does not
            // return the correct value for BigInts.
            return rb_ary_new3(2, rb_uint2inum(result),
                rb_str_substr(argv[0], offset, len - offset));
        }

        // Move to the next 7 bits
        shift += 7;
    }

    rb_raise(rb_eRuntimeError, "ULEB128 string did not contain a terminator");
}

.unpack_one_ruby(buf, endian: default_endian) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

provide a method for unpacking an instance of this type from a String, and returning both the unpacked value, and any unused input

Raises:

  • (TerminatorNotFoundError)


44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/elf_utils/types/uleb128.rb', line 44

def self.unpack_one_ruby(buf, endian: default_endian)
  value = 0
  shift = 0
  len = 0
  buf.each_byte do |b|
    len += 1
    value |= ((b & 0x7f) << shift)
    return value, buf.byteslice(len...) if (b & 0x80) == 0
    shift += 7
  end
  raise TerminatorNotFoundError
end