mirror of
https://github.com/ksherlock/merlin-utils.git
synced 2025-01-13 18:30:00 +00:00
add support for -D defines
fix segfault (switch id to be 0-based) handle absolute symbols
This commit is contained in:
parent
43fd7a1b6e
commit
debb2aebe9
98
link.cpp
98
link.cpp
@ -1,11 +1,13 @@
|
|||||||
/* c++17 */
|
/* c++17 */
|
||||||
|
|
||||||
#include <vector>
|
#include <algorithm>
|
||||||
#include <unordered_map>
|
#include <charconv>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <algorithm>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -59,9 +61,9 @@ std::vector<omf::segment> segments;
|
|||||||
symbol *find_symbol(const std::string &name) {
|
symbol *find_symbol(const std::string &name) {
|
||||||
|
|
||||||
auto iter = symbol_map.find(name);
|
auto iter = symbol_map.find(name);
|
||||||
if (iter != symbol_map.end()) return &symbol_table[iter->second - 1];
|
if (iter != symbol_map.end()) return &symbol_table[iter->second];
|
||||||
|
|
||||||
unsigned id = symbol_table.size() + 1;
|
unsigned id = symbol_table.size();
|
||||||
symbol_map.emplace(name, id);
|
symbol_map.emplace(name, id);
|
||||||
|
|
||||||
auto &rv = symbol_table.emplace_back();
|
auto &rv = symbol_table.emplace_back();
|
||||||
@ -222,7 +224,7 @@ void process_reloc(byte_view &data, cookie &cookie) {
|
|||||||
/* x = local symbol # */
|
/* x = local symbol # */
|
||||||
pending_reloc r;
|
pending_reloc r;
|
||||||
assert(x < cookie.remap.size());
|
assert(x < cookie.remap.size());
|
||||||
r.id = cookie.remap[x]; /* label reference is 0-based */
|
r.id = cookie.remap[x];
|
||||||
r.size = size;
|
r.size = size;
|
||||||
r.offset = offset;
|
r.offset = offset;
|
||||||
r.value = value;
|
r.value = value;
|
||||||
@ -326,9 +328,29 @@ void finalize(void) {
|
|||||||
auto &seg = segments.back();
|
auto &seg = segments.back();
|
||||||
|
|
||||||
for (auto &r : relocations) {
|
for (auto &r : relocations) {
|
||||||
assert(r.id <= symbol_map.size());
|
assert(r.id < symbol_map.size());
|
||||||
const auto &label = symbol_table[r.id];
|
const auto &e = symbol_table[r.id];
|
||||||
r.value = label.value;
|
|
||||||
|
/* if this is an absolute value, do the math */
|
||||||
|
if (!e.defined) {
|
||||||
|
warnx("%s is not defined", e.name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.absolute) {
|
||||||
|
uint32_t value = e.value + r.value;
|
||||||
|
value >>= -r.shift;
|
||||||
|
|
||||||
|
unsigned offset = r.offset;
|
||||||
|
unsigned size = r.size;
|
||||||
|
while (size--) {
|
||||||
|
seg.data[offset++] = value & 0xff;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.value += e.value;
|
||||||
seg.relocs.emplace_back(r);
|
seg.relocs.emplace_back(r);
|
||||||
}
|
}
|
||||||
relocations.clear();
|
relocations.clear();
|
||||||
@ -360,12 +382,66 @@ void print_symbols(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void usage(int ex) {
|
void usage(int ex) {
|
||||||
|
|
||||||
fputs("merlin-link [-o outfile] infile...\n", stderr);
|
fputs("merlin-link [-o outfile] infile...\n", stderr);
|
||||||
exit(ex);
|
exit(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_define(std::string str) {
|
||||||
|
/* -D key[=value]
|
||||||
|
value = 0x, $, % or base 10 */
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
auto ix = str.find('=');
|
||||||
|
if (ix == 0) usage(EX_USAGE);
|
||||||
|
if (ix == str.npos) {
|
||||||
|
value = 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int base = 10;
|
||||||
|
auto pos = ++ix;
|
||||||
|
|
||||||
|
char c = str[pos]; /* returns 0 if == size */
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
|
case '%':
|
||||||
|
base = 2; ++pos; break;
|
||||||
|
case '$':
|
||||||
|
base = 16; ++pos; break;
|
||||||
|
case '0':
|
||||||
|
c = str[pos+1];
|
||||||
|
if (c == 'x' || c == 'X') {
|
||||||
|
base = 16; pos += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto end = str.data() + str.length();
|
||||||
|
auto r = std::from_chars(str.data() + pos, end, value, base);
|
||||||
|
if (r.ec != std::errc() || r.ptr != end)
|
||||||
|
usage(EX_USAGE);
|
||||||
|
|
||||||
|
str.resize(ix-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
symbol *e = find_symbol(str);
|
||||||
|
if (e->defined && e->absolute && e->value == value) return;
|
||||||
|
|
||||||
|
if (e->defined) {
|
||||||
|
warnx("%s previously defined", str.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->defined = true;
|
||||||
|
e->absolute = true;
|
||||||
|
e->file = "-D";
|
||||||
|
e->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
@ -374,13 +450,14 @@ int main(int argc, char **argv) {
|
|||||||
bool compress = true;
|
bool compress = true;
|
||||||
|
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "o:XC")) != -1) {
|
while ((c = getopt(argc, argv, "o:D:XC")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'o':
|
case 'o':
|
||||||
gs_out = optarg;
|
gs_out = optarg;
|
||||||
break;
|
break;
|
||||||
case 'X': express = false; break;
|
case 'X': express = false; break;
|
||||||
case 'C': compress = false; break;
|
case 'C': compress = false; break;
|
||||||
|
case 'D': add_define(optarg); break;
|
||||||
case ':':
|
case ':':
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
@ -404,6 +481,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finalize();
|
||||||
print_symbols();
|
print_symbols();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user