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(const std::shared_ptr<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
131 using Section::WriteFile;
132
133 offset_t WriteFile(std::ostream& out, offset_t bytes, offset_t offset = 0) const override
134 {
135 offset_t table_bytes = WriteTable(out, bytes, offset);
136 return table_bytes + Section::WriteFile(out, bytes - table_bytes, offset + table_bytes);
137 }
138
139 offset_t WriteFile(const std::shared_ptr<Writer>& wr, offset_t bytes, offset_t offset = 0) const override
140 {
141 offset_t table_bytes = WriteTable(wr, bytes, offset);
142 return table_bytes + Buffer::WriteFile(wr, bytes - table_bytes, offset + table_bytes);
143 }
144
145 size_t ReadData(size_t bytes, offset_t offset, void * buffer) const override
146 {
147 Linker::FatalError("Fatal error: ReadData not implemented");
148 }
149
150 void Reset() override
151 {
153 entries.clear();
154 }
155 };
156
158 template <typename Int>
159 struct Word
160 {
161 public:
162 static constexpr offset_t EntrySize = sizeof(Int);
163
164 static void ReadFile(std::istream& in, Word& word, ::EndianType endian_type)
165 {
166 auto rd = std::make_shared<StreamReader>(endian_type, in);
167 ReadFile(rd, word);
168 }
169
170 static void ReadFile(const std::shared_ptr<Reader>& rd, Word& word, ::EndianType endian_type = ::UndefinedEndian)
171 {
172 (void) endian_type; // ignored
173 word.value = rd->ReadUnsigned(EntrySize); // TODO: ReadSigned for signed words
174 }
175
176 static void WriteFile(std::ostream& out, const Word& word, ::EndianType endian_type, offset_t bytes = EntrySize, offset_t offset = 0)
177 {
178 auto wr = std::make_shared<StreamWriter>(endian_type, &out);
179 WriteFile(wr, word, endian_type, bytes, offset);
180 }
181
182 static void WriteFile(const std::shared_ptr<Writer>& wr, const Word& word, ::EndianType endian_type = ::UndefinedEndian, offset_t bytes = EntrySize, offset_t offset = 0)
183 {
184 (void) endian_type; // ignored
185 // TODO: not dealing with partial entries for now
186 assert(bytes == EntrySize);
187 assert(offset == 0);
188 wr->WriteWord(EntrySize, word.value);
189 }
190
192 Int value = 0;
193 };
194
195 // TODO: uint64_t
197 class GOTEntry : public Word<uint32_t>
198 {
199 public:
200 std::optional<Target> target;
201
202 GOTEntry()
203 : target()
204 {
205 }
206
207 GOTEntry(Target target)
208 : target(target)
209 {
210 }
211
212 bool operator ==(const GOTEntry& other) const
213 {
214 return target == other.target;
215 }
216 };
217
219 class GlobalOffsetTable : public TableSection<GOTEntry>
220 {
221 public:
222 GlobalOffsetTable(::EndianType endian_type, std::string name, int flags = Readable)
224 {
225 }
226
227 GlobalOffsetTable(std::string name, int flags = Readable)
229 {
230 }
231
232 void AddEntry(GOTEntry entry)
233 {
234 if(std::find(entries.begin(), entries.end(), entry) == entries.end())
235 {
236 entries.push_back(entry);
237 }
238 }
239 };
240}
241
242#endif /* TABLE_SECTION_H */
offset_t WriteFile(const std::shared_ptr< Writer > &wr, offset_t count, offset_t offset=0) const override
Writes data of non-zero filled sections.
Definition buffer.cc:108
virtual offset_t WriteFile(const std::shared_ptr< Writer > &wr) const =0
Writes data of non-zero filled sections.
An entry in the Global Offset Table.
Definition table_section.h:198
A generated Global Offset Table.
Definition table_section.h:220
A section of data as read from an object file.
Definition section.h:28
virtual void Reset()
Clear the section.
Definition section.cc:363
virtual offset_t WriteFile(std::ostream &out, offset_t bytes, offset_t offset=0) const
Writes data into file.
Definition section.cc:349
virtual void ReadFile(std::istream &in)
Overwrites section data with contents of input stream.
Definition section.cc:337
std::string name
Name of the section.
Definition section.h:33
@ Readable
The data in the section can be read at runtime.
Definition section.h:47
@ ZeroFilled
Section is filled with zeros.
Definition section.h:73
section_flags flags
The type of the section.
Definition section.h:109
An automatically generated section that stores a table of equally sized entries.
Definition table_section.h:19
void ReadFile(const std::shared_ptr< Reader > &rd) override
Overwrites section data with contents of reader.
Definition table_section.h:58
offset_t WriteFile(std::ostream &out, offset_t bytes, offset_t offset=0) const override
Writes data into file.
Definition table_section.h:133
void Reset() override
Clear the section.
Definition table_section.h:150
std::vector< TableEntryType > entries
List of entries to be stored in the table.
Definition table_section.h:24
offset_t WriteTable(OutputType &out, offset_t bytes, offset_t offset) const
Generic function to handle writing entries.
Definition table_section.h:69
offset_t WriteFile(const std::shared_ptr< Writer > &wr, offset_t bytes, offset_t offset=0) const override
Writes data of non-zero filled sections.
Definition table_section.h:139
::EndianType endian_type
Endianness of table entries.
Definition table_section.h:22
size_t ReadData(size_t bytes, offset_t offset, void *buffer) const override
Attempts to fill a buffer with data.
Definition table_section.h:145
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
Generic template to be used as table entries.
Definition table_section.h:160
Int value
The value to be stored.
Definition table_section.h:192