From 4f7890c6992de3c0bc4a491c65e7927511b0b8ce Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Mon, 1 Jun 2020 00:15:39 -0400 Subject: [PATCH] Merling DDB support. 2-byte data stored in big-endian format, which requires 2 1-byte relocation records. --- link.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/link.cpp b/link.cpp index 5867338..fb48a12 100644 --- a/link.cpp +++ b/link.cpp @@ -317,6 +317,8 @@ static void process_reloc(byte_view &data, cookie &cookie) { offset += cookie.begin; bool external = false; + bool ddb = false; + unsigned shift = 0; uint32_t value = 0; unsigned size = 0; @@ -366,6 +368,12 @@ static void process_reloc(byte_view &data, cookie &cookie) { case 0x90: size = 2; break; + case 0xa0: + case 0xb0: + /* ddb */ + size = 2; + ddb = true; + break; default: /* bad size */ errx(1, "%s: Unsupported flag: %02x\n", cookie.file.c_str(), flag); break; @@ -373,12 +381,16 @@ static void process_reloc(byte_view &data, cookie &cookie) { external = flag & 0x10; assert(offset + size <= cookie.end); + + switch(size) { case 3: value |= seg.data[offset+2] << 16; case 2: value |= seg.data[offset+1] << 8; case 1: value |= seg.data[offset+0]; } + if (ddb) value = ((value >> 8) | (value << 8)) & 0xffff; + if (flag & 0x40) { /* value is already shifted, so need to adjust back */ value <<= 8; @@ -390,6 +402,53 @@ static void process_reloc(byte_view &data, cookie &cookie) { } + /* clear out the inline relocation data */ + for (unsigned i = 0; i < size; ++i) { + seg.data[offset + i] = 0; + } + + if (ddb) { + /* + * ddb - data is stored inline in big-endian format. + * generate 1-byte, -8 shift for offset+0 + * generate 1-byte, 0 shift for offset+1 + */ + + + if (external) { + pending_reloc r; + assert(x < cookie.remap.size()); + r.id = cookie.remap[x]; + r.size = 1; + r.offset = offset; + r.value = value; + r.shift = -8; + + symbol_table[r.id].count += 1; + pending.emplace_back(r); + + pending.emplace_back(r); + r.offset++; + r.shift = 0; + pending.emplace_back(r); + + } else { + + omf::reloc r; + r.size = 1; + r.offset = offset; + r.value = value + cookie.begin; + r.shift = -8; + + seg.relocs.emplace_back(r); + + r.offset++; + r.shift = 0; + seg.relocs.emplace_back(r); + } + return; + } + /* external resolutions are deferred for later */ if (external) { /* x = local symbol # */ @@ -412,10 +471,7 @@ static void process_reloc(byte_view &data, cookie &cookie) { seg.relocs.emplace_back(r); } - /* clear out the inline relocation data */ - for (unsigned i = 0; i < size; ++i) { - seg.data[offset + i] = 0; - } + //cookie.zero.emplace_back(std::make_pair(offset, size)); } }