add support for $4F relocation record, which is a 1-byte, internal relocation with 8-bit shift. Found via linking marinetti.

This commit is contained in:
Kelvin Sherlock 2019-12-21 15:07:03 -05:00
parent 67f34936c2
commit c85d401fbf

View File

@ -346,21 +346,21 @@ static void process_reloc(byte_view &data, cookie &cookie) {
} }
data.remove_prefix(4); data.remove_prefix(4);
} else { } else {
assert((flag & ~(0x0f|0x10|0x20|0x80)) == 0);
// offset already adjusted by start so below comparisons are wrong. // offset already adjusted by start so below comparisons are wrong.
switch(flag & (0x80 + 0x20)) { switch(flag & (0x80 | 0x40 | 0x20)) {
case 0: case 0:
size = 1; size = 1;
assert(offset + 0 < cookie.end);
break; break;
case 0x20: case 0x20:
size = 3; size = 3;
assert(offset + 2 < cookie.end); break;
case 0x40:
size = 1;
shift = -8;
break; break;
case 0x80: case 0x80:
size = 2; size = 2;
assert(offset + 1 < cookie.end);
break; break;
default: /* bad size */ default: /* bad size */
errx(1, "%s: Unsupported flag: %02x\n", cookie.file.c_str(), flag); errx(1, "%s: Unsupported flag: %02x\n", cookie.file.c_str(), flag);
@ -368,13 +368,19 @@ static void process_reloc(byte_view &data, cookie &cookie) {
} }
external = flag & 0x10; external = flag & 0x10;
assert(offset + size <= cookie.end);
switch(size) { switch(size) {
case 3: value |= seg.data[offset+2] << 16; case 3: value |= seg.data[offset+2] << 16;
case 2: value |= seg.data[offset+1] << 8; case 2: value |= seg.data[offset+1] << 8;
case 1: value |= seg.data[offset+0]; case 1: value |= seg.data[offset+0];
} }
if (flag & 0x40) {
/* value is already shifted, so need to adjust back */
value <<= 8;
value -= 0x8000;
assert(!external);
}
if (size > 1) value -= 0x8000; if (size > 1) value -= 0x8000;
} }
@ -415,6 +421,7 @@ static void process_unit(const std::string &path) {
cookie cookie; cookie cookie;
/* skip over relocs, do symbols first */ /* skip over relocs, do symbols first */
if (verbose) printf("Linking %s\n", path.c_str());
std::error_code ec; std::error_code ec;
mapped_file mf(path, mapped_file::readonly, ec); mapped_file mf(path, mapped_file::readonly, ec);