RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
table_section.h
1#ifndef TABLE_SECTION_H
2#define TABLE_SECTION_H
3
4#include "../common.h"
5#include "reader.h"
6#include "section.h"
7#include "target.h"
8#include "writer.h"
9
10namespace Linker
11{
17 template <typename TableEntryType>
18 class TableSection : public Section
19 {
20 public:
22 ::EndianType endian_type = ::UndefinedEndian;
24 std::vector<TableEntryType> entries;
25
26 TableSection(::EndianType endian_type, std::string name, int flags = Readable)
28 {
29 assert(!(flags & ZeroFilled));
30 }
31
32 TableSection(std::string name, int flags = Readable)
34 {
35 assert(!(flags & ZeroFilled));
36 }
37
38 offset_t Size() const override
39 {
40 return entries.size() * TableEntryType::EntrySize + data.size();
41 }
42
43 offset_t SetZeroFilled(bool is_zero_filled) override
44 {
45 assert(!is_zero_filled);
46 return 0;
47 }
48
49 void ReadFile(std::istream& in) override
50 {
51 for(auto& entry : entries)
52 {
53 TableEntryType::ReadFile(in, entry, endian_type);
54 }
56 }
57
58 void ReadFile(Reader& rd) override
59 {
60 for(auto& entry : entries)
61 {
62 TableEntryType::ReadFile(rd, entry, endian_type);
63 }
65 }
66
68 template <typename OutputType>
69 offset_t WriteTable(OutputType& out, offset_t bytes, offset_t offset) const
70 {
71 if(offset / TableEntryType::EntrySize >= entries.size())
72 return 0;
73
74 bytes = std::min(bytes, entries.size() * TableEntryType::EntrySize - offset);
75
76 offset_t output_byte_count = 0;
77 offset_t offset_in_entry = offset % TableEntryType::EntrySize;
78 if(offset_in_entry != 0)
79 {
80 if(offset + bytes >= TableEntryType::EntrySize)
81 {
82 // write first partial entry
83 TableEntryType::WriteFile(out, entries[offset / TableEntryType::EntrySize],
85 TableEntryType::EntrySize,
86 offset_in_entry);
87 output_byte_count += TableEntryType::EntrySize - offset_in_entry;
88 offset += TableEntryType::EntrySize - offset_in_entry;
89 }
90 else
91 {
92 // write only partial entry
93 TableEntryType::WriteFile(out, entries[offset / TableEntryType::EntrySize],
95 bytes - offset_in_entry,
96 offset_in_entry);
97 output_byte_count += bytes;
98 offset += bytes;
99 bytes = 0;
100 }
101 }
102
103 for(
104 offset_t entry_index = offset / TableEntryType::EntrySize;
105 entry_index < entries.size() && entry_index < (offset + bytes) / TableEntryType::EntrySize;
106 entry_index++)
107 {
108 // write full entries
109 TableEntryType::WriteFile(out, entries[entry_index], endian_type);
110 output_byte_count += TableEntryType::EntrySize;
111 }
112
113 if(offset / TableEntryType::EntrySize < entries.size())
114 {
115 offset_t bytes_in_entry = bytes % TableEntryType::EntrySize;
116 if(bytes_in_entry != 0)
117 {
118 // write last partial entry
119 TableEntryType::WriteFile(out, entries[offset / TableEntryType::EntrySize],
121 bytes_in_entry,
122 offset);
123 output_byte_count += bytes;
124 }
125 }
126
127 return output_byte_count;
128 }
129
130 using Section::WriteFile;
131
132 offset_t WriteFile(std::ostream& out, offset_t bytes, offset_t offset = 0) const override
133 {
134 offset_t table_bytes = WriteTable(out, bytes, offset);
135 return table_bytes + Section::WriteFile(out, bytes - table_bytes, offset + table_bytes);
136 }
137
138 offset_t WriteFile(Writer& wr, offset_t bytes, offset_t offset = 0) const override
139 {
140 offset_t table_bytes = WriteTable(wr, bytes, offset);
141 return table_bytes + Buffer::WriteFile(wr, bytes - table_bytes, offset + table_bytes);
142 }
143
144 void Reset() override
145 {
147 entries.clear();
148 }
149 };
150
152 template <typename Int>
153 struct Word
154 {
155 public:
156 static constexpr offset_t EntrySize = sizeof(Int);
157
158 static void ReadFile(std::istream& in, Word& word, ::EndianType endian_type)
159 {
160 Reader rd(endian_type, &in);
161 ReadFile(rd, word);
162 }
163
164 static void ReadFile(Reader& rd, Word& word, ::EndianType endian_type = ::UndefinedEndian)
165 {
166 (void) endian_type; // ignored
167 word.value = rd.ReadUnsigned(EntrySize); // TODO: ReadSigned for signed words
168 }
169
170 static void WriteFile(std::ostream& out, const Word& word, ::EndianType endian_type, offset_t bytes = EntrySize, offset_t offset = 0)
171 {
172 Writer wr(endian_type, &out);
173 WriteFile(wr, word, endian_type, bytes, offset);
174 }
175
176 static void WriteFile(Writer& wr, const Word& word, ::EndianType endian_type = ::UndefinedEndian, offset_t bytes = EntrySize, offset_t offset = 0)
177 {
178 (void) endian_type; // ignored
179 // TODO: not dealing with partial entries for now
180 assert(bytes == EntrySize);
181 assert(offset == 0);
182 wr.WriteWord(EntrySize, word.value);
183 }
184
186 Int value;
187 };
188
189 // TODO: uint64_t
191 class GOTEntry : public Word<uint32_t>
192 {
193 public:
194 std::optional<Target> target;
195
196 GOTEntry()
197 : target()
198 {
199 }
200
201 GOTEntry(Target target)
202 : target(target)
203 {
204 }
205
206 bool operator ==(const GOTEntry& other) const
207 {
208 return target == other.target;
209 }
210 };
211
213 class GlobalOffsetTable : public TableSection<GOTEntry>
214 {
215 public:
216 GlobalOffsetTable(::EndianType endian_type, std::string name, int flags = Readable)
218 {
219 }
220
221 GlobalOffsetTable(std::string name, int flags = Readable)
223 {
224 }
225
226 void AddEntry(GOTEntry entry)
227 {
228 if(std::find(entries.begin(), entries.end(), entry) == entries.end())
229 {
230 entries.push_back(entry);
231 }
232 }
233 };
234}
235
236#endif /* TABLE_SECTION_H */
offset_t WriteFile(Writer &wr, offset_t count, offset_t offset=0) const override
Writes data of non-zero filled sections.
Definition buffer.cc:43
An entry in the Global Offset Table.
Definition table_section.h:192
A generated Global Offset Table.
Definition table_section.h:214
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:16
uint64_t ReadUnsigned(size_t bytes, EndianType endiantype)
Read an unsigned word.
Definition reader.cc:86
A section of data as read from an object file.
Definition section.h:24
virtual void Reset()
Clear the section.
Definition section.cc:369
virtual offset_t WriteFile(std::ostream &out, offset_t bytes, offset_t offset=0) const
Writes data into file.
Definition section.cc:355
virtual void ReadFile(std::istream &in)
Overwrites section data with contents of input stream.
Definition section.cc:343
std::string name
Name of the section.
Definition section.h:29
@ Readable
The data in the section can be read at runtime.
Definition section.h:43
@ ZeroFilled
Section is filled with zeros.
Definition section.h:69
section_flags flags
The type of the section.
Definition section.h:105
An automatically generated section that stores a table of equally sized entries.
Definition table_section.h:19
offset_t WriteFile(std::ostream &out, offset_t bytes, offset_t offset=0) const override
Writes data into file.
Definition table_section.h:132
void Reset() override
Clear the section.
Definition table_section.h:144
std::vector< TableEntryType > entries
List of entries to be stored in the table.
Definition table_section.h:24
offset_t WriteFile(Writer &wr, offset_t bytes, offset_t offset=0) const override
Writes data of non-zero filled sections.
Definition table_section.h:138
offset_t WriteTable(OutputType &out, offset_t bytes, offset_t offset) const
Generic function to handle writing entries.
Definition table_section.h:69
::EndianType endian_type
Endianness of table entries.
Definition table_section.h:22
void ReadFile(Reader &rd) override
Overwrites section data with contents of input stream.
Definition table_section.h:58
void ReadFile(std::istream &in) override
Overwrites section data with contents of input stream.
Definition table_section.h:49
Represents a possible target or reference frame of a relocation.
Definition target.h:24
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15
void WriteWord(size_t bytes, uint64_t value, EndianType endiantype)
Read a word.
Definition writer.cc:66
Generic template to be used as table entries.
Definition table_section.h:154
Int value
The value to be stored.
Definition table_section.h:186