| ... | ... | @@ -193,6 +193,7 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 193 | 193 | @disableInstrumentation(); |
| 194 | 194 | |
| 195 | 195 | const dynv = getDynamicSymbol(); |
| 196 | |
| 196 | 197 | // Recover the delta applied by the loader by comparing the effective and |
| 197 | 198 | // the theoretical load addresses for the `_DYNAMIC` symbol. |
| 198 | 199 | const base_addr = base: { |
| ... | ... | @@ -204,34 +205,45 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 204 | 205 | @trap(); |
| 205 | 206 | }; |
| 206 | 207 | |
| 207 | | var rel_addr: usize = 0; |
| 208 | | var rela_addr: usize = 0; |
| 209 | | var rel_size: usize = 0; |
| 210 | | var rela_size: usize = 0; |
| 208 | var sorted_dynv: [elf.DT_NUM]elf.Addr = undefined; |
| 209 | |
| 210 | // Zero-initialized this way to prevent the compiler from turning this into |
| 211 | // `memcpy` or `memset` calls (which can require relocations). |
| 212 | for (&sorted_dynv) |*dyn| { |
| 213 | const pdyn: *volatile elf.Addr = @ptrCast(dyn); |
| 214 | pdyn.* = 0; |
| 215 | } |
| 216 | |
| 211 | 217 | { |
| 218 | // `dynv` has no defined order. Fix that. |
| 212 | 219 | var i: usize = 0; |
| 213 | 220 | while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) { |
| 214 | | switch (dynv[i].d_tag) { |
| 215 | | elf.DT_REL => rel_addr = base_addr + dynv[i].d_val, |
| 216 | | elf.DT_RELA => rela_addr = base_addr + dynv[i].d_val, |
| 217 | | elf.DT_RELSZ => rel_size = dynv[i].d_val, |
| 218 | | elf.DT_RELASZ => rela_size = dynv[i].d_val, |
| 219 | | else => {}, |
| 220 | | } |
| 221 | if (dynv[i].d_tag < elf.DT_NUM) sorted_dynv[@bitCast(dynv[i].d_tag)] = dynv[i].d_val; |
| 221 | 222 | } |
| 222 | 223 | } |
| 223 | 224 | |
| 224 | | // Apply the relocations. |
| 225 | | if (rel_addr != 0) { |
| 226 | | const rel = std.mem.bytesAsSlice(elf.Rel, @as([*]u8, @ptrFromInt(rel_addr))[0..rel_size]); |
| 227 | | for (rel) |r| { |
| 225 | |
| 226 | // Apply normal relocations. |
| 227 | |
| 228 | const rel = sorted_dynv[elf.DT_REL]; |
| 229 | if (rel != 0) { |
| 230 | const rels = @call(.always_inline, std.mem.bytesAsSlice, .{ |
| 231 | elf.Rel, |
| 232 | @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], |
| 233 | }); |
| 234 | for (rels) |r| { |
| 228 | 235 | if (r.r_type() != R_RELATIVE) continue; |
| 229 | 236 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr; |
| 230 | 237 | } |
| 231 | 238 | } |
| 232 | | if (rela_addr != 0) { |
| 233 | | const rela = std.mem.bytesAsSlice(elf.Rela, @as([*]u8, @ptrFromInt(rela_addr))[0..rela_size]); |
| 234 | | for (rela) |r| { |
| 239 | |
| 240 | const rela = sorted_dynv[elf.DT_RELA]; |
| 241 | if (rela != 0) { |
| 242 | const relas = @call(.always_inline, std.mem.bytesAsSlice, .{ |
| 243 | elf.Rela, |
| 244 | @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], |
| 245 | }); |
| 246 | for (relas) |r| { |
| 235 | 247 | if (r.r_type() != R_RELATIVE) continue; |
| 236 | 248 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend)); |
| 237 | 249 | } |