Skip to content

Commit 6b8abad

Browse files
committed
parse shstrtab
1 parent 940424b commit 6b8abad

File tree

8 files changed

+99
-22
lines changed

8 files changed

+99
-22
lines changed

lib/caotral/linker/elf/header.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,20 @@ def set!(entry: nil, phoffset: nil, shoffset: nil, shnum: nil, shstrndx: nil)
3535
@shstrndx = num2bytes(shstrndx, 2) if check(shstrndx, 2)
3636
end
3737

38-
private
38+
def ehsize = get(:ehsize)
39+
def phsize = get(:phsize)
40+
def phnum = get(:phnum)
41+
def shentsize = get(:shentsize)
42+
def shnum = get(:shnum)
43+
def shstrndx = get(:shstrndx)
44+
45+
LONG_TYPES = %w[entry phoffset shoffset].freeze
46+
INT_TYPES = %w[type version].freeze
47+
SHORT_TYPES = %w[ehsize phsize phnum shentsize shnum shstrndx].freeze
48+
CHAR_TYPES = %w[arch flags].freeze
49+
private_constant :LONG_TYPES, :INT_TYPES, :SHORT_TYPES, :CHAR_TYPES
3950

51+
private
4052
def bytes = [
4153
@ident, @type, @arch, @version, @entry, @phoffset,
4254
@shoffset, @flags, @ehsize, @phsize, @phnum, @shentsize,
@@ -62,6 +74,18 @@ def elf(type)
6274
:NONE
6375
end
6476
end
77+
78+
def get(type)
79+
val = instance_variable_get(:"@#{type.to_s}").pack("C*")
80+
case type.to_s.downcase
81+
when *LONG_TYPES; val.unpack("Q<")
82+
when *INT_TYPES; val.unpack("L<")
83+
when *SHORT_TYPES; val.unpack("S<")
84+
when *CHAR_TYPES; val.unpack("C<")
85+
else
86+
raise "not specified: #{type}"
87+
end.first
88+
end
6589
end
6690
end
6791
end

lib/caotral/linker/elf/section.rb

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
class Caotral::Linker::ELF::Section
2-
attr_accessor :name, :header
3-
attr_reader :section_name, :body
4-
def initialize(type:, options: {})
5-
type_string = type.to_s.capitalize
6-
type_string = type_string.upcase if type_string == "Bss"
7-
# section_name is extra information about section type
8-
@section_name = type_string.downcase
9-
# name is used in section header string table in elf file
10-
@name = section_name == "null" ? "" : "\0.#{section_name}"
11-
@header, @body = nil, nil
1+
class Caotral::Linker
2+
class ELF
3+
class Section
4+
attr_accessor :name, :header, :body, :section_name
5+
def initialize(type:, options: {})
6+
type_string = type.to_s.capitalize
7+
type_string = type_string.upcase if type_string == "Bss"
8+
@section_name = type.to_s.downcase
9+
# name is used in section header string table in elf file
10+
@name = section_name == "null" ? "" : "\0.#{section_name}"
11+
@header, @body = nil, nil
12+
end
13+
end
1214
end
1315
end

lib/caotral/linker/elf/section/shstrtab.rb

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
class Caotral::Linker::ELF::Section::Strtab
2-
include Caotral::Assembler::ELF::Utils
3-
def initialize(names = "\0main\0", **opts) = @names = names
4-
def build = @names.bytes.pack("C*")
1+
module Caotral
2+
class Linker
3+
class ELF
4+
class Section
5+
class Strtab
6+
include Caotral::Assembler::ELF::Utils
7+
attr_reader :names
8+
def initialize(names = "\0main\0", **opts) = @names = names
9+
def build = @names.bytes.pack("C*")
10+
end
11+
end
12+
end
13+
end
514
end

lib/caotral/linker/elf/section_header.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,24 @@ def set!(name: nil, type: nil, flags: nil, addr: nil,
5050
end
5151

5252
def null! = set!(name: 0, type: 0, flags: 0, addr: 0, offset: 0, size: 0, link: 0, info: 0, addralign: 0, entsize: 0)
53+
def name = get(:name)
54+
def offset = get(:offset)
55+
def size = get(:size)
56+
LONG_TYPES = %w[flags addr offset size addralign entsize].freeze
57+
INT_TYPES = %w[name type link info].freeze
58+
59+
private_constant :LONG_TYPES, :INT_TYPES
5360

5461
private def bytes = [@name, @type, @flags, @addr, @offset, @size, @link, @info, @addralign, @entsize]
62+
private def get(type)
63+
val = instance_variable_get("@#{type.to_s}").pack("C*")
64+
case type.to_s
65+
when *INT_TYPES; val.unpack("L<")
66+
when *LONG_TYPES; val.unpack("Q<")
67+
else
68+
raise "not specified: #{type}"
69+
end.first
70+
end
5571
end
5672
end
5773
end

lib/caotral/linker/reader.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require_relative "elf"
33
require_relative "elf/section"
44
require_relative "elf/section_header"
5+
require_relative "elf/section/strtab"
56

67
module Caotral
78
class Linker
@@ -47,6 +48,13 @@ def read
4748
section.header = section_header
4849
@context.sections.add(section)
4950
end
51+
@context.sections[shstrndx].tap do |shstrtab|
52+
@bin.pos = shstrtab.header.offset
53+
names = @bin.read(shstrtab.header.size)
54+
shstrtab.section_name = "shstrtab"
55+
shstrtab.name = "\0.shstrtab"
56+
shstrtab.body = Caotral::Linker::ELF::Section::Strtab.new(names)
57+
end
5058
@context
5159
ensure
5260
@input.close
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11
class Caotral::Linker::ELF::SectionHeader
22
SHT: Hash[Symbol, Integer]
33
SHT_BY_VALUE: Hash[Integer, Symbol]
4+
LONG_TYPES: Array[String]
5+
INT_TYPES: Array[String]
6+
7+
def initialize: () -> void
8+
def build: () -> String
9+
def set!: (
10+
?name: Integer?,
11+
?type: Integer?,
12+
?flags: Integer?,
13+
?addr: Integer?,
14+
?offset: Integer?,
15+
?size: Integer?,
16+
?link: Integer?,
17+
?info: Integer?,
18+
?addralign: Integer?,
19+
?entsize: Integer?
20+
) -> self
21+
def null!: () -> self
22+
def name: () -> Integer
23+
def offset: () -> Integer
24+
def size: () -> Integer
425
end

test/caotral/linker/reader_test.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ def test_read
88
assert_equal elf_obj.header.shoffset.pack("C*").unpack("Q<").first, 256
99
assert_equal elf_obj.sections.size, 8
1010
assert_equal elf_obj.sections[0].section_name, "null"
11+
shstrtab = elf_obj.sections[elf_obj.header.shstrndx]
12+
assert_equal shstrtab.section_name, "shstrtab"
13+
assert_equal shstrtab.body.names, "\0.text\0.data\0.bss\0.note\0.symtab\0.strtab\0.shstrtab\0"
1114
end
1215
end

0 commit comments

Comments
 (0)