authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-11 17:34:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-11 17:34:12-04:00
log3657a54618dafa110fd1d16e02c48e04871c9370
tree862f790ed9550daa21eaeed9a33a7d97409dfad3
parent6892865ba72ea220a12a8238ce78aedab1237cce
signaturelock-open Commit is signed but in an unrecognized format.

fix regressions in elf parsing code


2 files changed, 133 insertions(+), 39 deletions(-)

lib/std/elf.zig+117-38
...@@ -398,48 +398,123 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {...@@ -398,48 +398,123 @@ pub fn readAllHeaders(allocator: *mem.Allocator, file: File) !AllHeaders {
398 const need_bswap = hdrs.header.endian != std.builtin.endian;398 const need_bswap = hdrs.header.endian != std.builtin.endian;
399399
400 hdrs.section_headers = try allocator.alloc(Elf64_Shdr, hdrs.header.shnum);400 hdrs.section_headers = try allocator.alloc(Elf64_Shdr, hdrs.header.shnum);
401 errdefer hdrs.allocator.free(hdrs.section_headers);401 errdefer allocator.free(hdrs.section_headers);
402402
403 hdrs.program_headers = try allocator.alloc(Elf64_Phdr, hdrs.header.phnum);403 hdrs.program_headers = try allocator.alloc(Elf64_Phdr, hdrs.header.phnum);
404 errdefer hdrs.allocator.free(hdrs.program_headers);404 errdefer allocator.free(hdrs.program_headers);
405405
406 // Treat section headers and program headers as byte buffers. For 32-bit ELF and406 // If the ELF file is 64-bit and same-endianness, then all we have to do is
407 // non-matching endian files, we post-process to correct integer endianness and offsets.407 // yeet the bytes into memory.
408 // If only the endianness is different, they can be simply byte swapped.
409 if (is_64) {
410 const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers);
411 const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers);
412 try preadNoEof(file, shdr_buf, hdrs.header.shoff);
413 try preadNoEof(file, phdr_buf, hdrs.header.phoff);
414
415 if (need_bswap) {
416 for (hdrs.section_headers) |*shdr| {
417 shdr.* = .{
418 .sh_name = @byteSwap(@TypeOf(shdr.sh_name), shdr.sh_name),
419 .sh_type = @byteSwap(@TypeOf(shdr.sh_type), shdr.sh_type),
420 .sh_flags = @byteSwap(@TypeOf(shdr.sh_flags), shdr.sh_flags),
421 .sh_addr = @byteSwap(@TypeOf(shdr.sh_addr), shdr.sh_addr),
422 .sh_offset = @byteSwap(@TypeOf(shdr.sh_offset), shdr.sh_offset),
423 .sh_size = @byteSwap(@TypeOf(shdr.sh_size), shdr.sh_size),
424 .sh_link = @byteSwap(@TypeOf(shdr.sh_link), shdr.sh_link),
425 .sh_info = @byteSwap(@TypeOf(shdr.sh_info), shdr.sh_info),
426 .sh_addralign = @byteSwap(@TypeOf(shdr.sh_addralign), shdr.sh_addralign),
427 .sh_entsize = @byteSwap(@TypeOf(shdr.sh_entsize), shdr.sh_entsize),
428 };
429 }
430 for (hdrs.program_headers) |*phdr| {
431 phdr.* = .{
432 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
433 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
434 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
435 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
436 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
437 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
438 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
439 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
440 };
441 }
442 }
443
444 return hdrs;
445 }
408446
409 const shdr_buf = std.mem.sliceAsBytes(hdrs.section_headers)[0 .. hdrs.header.shentsize * hdrs.header.shnum];447 const shdrs_32 = try allocator.alloc(Elf32_Shdr, hdrs.header.shnum);
410 const phdr_buf = std.mem.sliceAsBytes(hdrs.program_headers)[0 .. hdrs.header.phentsize * hdrs.header.phnum];448 defer allocator.free(shdrs_32);
411449
450 const phdrs_32 = try allocator.alloc(Elf32_Phdr, hdrs.header.phnum);
451 defer allocator.free(phdrs_32);
452
453 const shdr_buf = std.mem.sliceAsBytes(shdrs_32);
454 const phdr_buf = std.mem.sliceAsBytes(phdrs_32);
412 try preadNoEof(file, shdr_buf, hdrs.header.shoff);455 try preadNoEof(file, shdr_buf, hdrs.header.shoff);
413 try preadNoEof(file, phdr_buf, hdrs.header.phoff);456 try preadNoEof(file, phdr_buf, hdrs.header.phoff);
414457
415 const shdrs32 = @ptrCast([*]Elf32_Shdr, @alignCast(@alignOf(Elf32_Shdr), shdr_buf.ptr))[0..hdrs.header.shnum];458 if (need_bswap) {
416 const phdrs32 = @ptrCast([*]Elf32_Phdr, @alignCast(@alignOf(Elf32_Phdr), phdr_buf.ptr))[0..hdrs.header.phnum];459 for (hdrs.section_headers) |*shdr, i| {
417 for (hdrs.section_headers) |*shdr, i| {460 const o = shdrs_32[i];
418 shdr.* = .{461 shdr.* = .{
419 .sh_name = int(is_64, need_bswap, shdrs32[i].sh_name, shdr.sh_name),462 .sh_name = @byteSwap(@TypeOf(o.sh_name), o.sh_name),
420 .sh_type = int(is_64, need_bswap, shdrs32[i].sh_type, shdr.sh_type),463 .sh_type = @byteSwap(@TypeOf(o.sh_type), o.sh_type),
421 .sh_flags = int(is_64, need_bswap, shdrs32[i].sh_flags, shdr.sh_flags),464 .sh_flags = @byteSwap(@TypeOf(o.sh_flags), o.sh_flags),
422 .sh_addr = int(is_64, need_bswap, shdrs32[i].sh_addr, shdr.sh_addr),465 .sh_addr = @byteSwap(@TypeOf(o.sh_addr), o.sh_addr),
423 .sh_offset = int(is_64, need_bswap, shdrs32[i].sh_offset, shdr.sh_offset),466 .sh_offset = @byteSwap(@TypeOf(o.sh_offset), o.sh_offset),
424 .sh_size = int(is_64, need_bswap, shdrs32[i].sh_size, shdr.sh_size),467 .sh_size = @byteSwap(@TypeOf(o.sh_size), o.sh_size),
425 .sh_link = int(is_64, need_bswap, shdrs32[i].sh_link, shdr.sh_link),468 .sh_link = @byteSwap(@TypeOf(o.sh_link), o.sh_link),
426 .sh_info = int(is_64, need_bswap, shdrs32[i].sh_info, shdr.sh_info),469 .sh_info = @byteSwap(@TypeOf(o.sh_info), o.sh_info),
427 .sh_addralign = int(is_64, need_bswap, shdrs32[i].sh_addralign, shdr.sh_addralign),470 .sh_addralign = @byteSwap(@TypeOf(o.sh_addralign), o.sh_addralign),
428 .sh_entsize = int(is_64, need_bswap, shdrs32[i].sh_entsize, shdr.sh_entsize),471 .sh_entsize = @byteSwap(@TypeOf(o.sh_entsize), o.sh_entsize),
429 };472 };
430 }473 }
431 for (hdrs.program_headers) |*phdr, i| {474 for (hdrs.program_headers) |*phdr, i| {
432 phdr.* = .{475 const o = phdrs_32[i];
433 .p_type = int(is_64, need_bswap, phdrs32[i].p_type, phdr.p_type),476 phdr.* = .{
434 .p_offset = int(is_64, need_bswap, phdrs32[i].p_offset, phdr.p_offset),477 .p_type = @byteSwap(@TypeOf(o.p_type), o.p_type),
435 .p_vaddr = int(is_64, need_bswap, phdrs32[i].p_vaddr, phdr.p_vaddr),478 .p_offset = @byteSwap(@TypeOf(o.p_offset), o.p_offset),
436 .p_paddr = int(is_64, need_bswap, phdrs32[i].p_paddr, phdr.p_paddr),479 .p_vaddr = @byteSwap(@TypeOf(o.p_vaddr), o.p_vaddr),
437 .p_filesz = int(is_64, need_bswap, phdrs32[i].p_filesz, phdr.p_filesz),480 .p_paddr = @byteSwap(@TypeOf(o.p_paddr), o.p_paddr),
438 .p_memsz = int(is_64, need_bswap, phdrs32[i].p_memsz, phdr.p_memsz),481 .p_filesz = @byteSwap(@TypeOf(o.p_filesz), o.p_filesz),
439 .p_flags = int(is_64, need_bswap, phdrs32[i].p_flags, phdr.p_flags),482 .p_memsz = @byteSwap(@TypeOf(o.p_memsz), o.p_memsz),
440 .p_align = int(is_64, need_bswap, phdrs32[i].p_align, phdr.p_align),483 .p_flags = @byteSwap(@TypeOf(o.p_flags), o.p_flags),
441 };484 .p_align = @byteSwap(@TypeOf(o.p_align), o.p_align),
485 };
486 }
487 } else {
488 for (hdrs.section_headers) |*shdr, i| {
489 const o = shdrs_32[i];
490 shdr.* = .{
491 .sh_name = o.sh_name,
492 .sh_type = o.sh_type,
493 .sh_flags = o.sh_flags,
494 .sh_addr = o.sh_addr,
495 .sh_offset = o.sh_offset,
496 .sh_size = o.sh_size,
497 .sh_link = o.sh_link,
498 .sh_info = o.sh_info,
499 .sh_addralign = o.sh_addralign,
500 .sh_entsize = o.sh_entsize,
501 };
502 }
503 for (hdrs.program_headers) |*phdr, i| {
504 const o = phdrs_32[i];
505 phdr.* = .{
506 .p_type = o.p_type,
507 .p_offset = o.p_offset,
508 .p_vaddr = o.p_vaddr,
509 .p_paddr = o.p_paddr,
510 .p_filesz = o.p_filesz,
511 .p_memsz = o.p_memsz,
512 .p_flags = o.p_flags,
513 .p_align = o.p_align,
514 };
515 }
442 }516 }
517
443 return hdrs;518 return hdrs;
444}519}
445520
...@@ -451,11 +526,15 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_...@@ -451,11 +526,15 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_
451 return int_64;526 return int_64;
452 }527 }
453 } else {528 } else {
454 if (need_bswap) {529 return int32(need_bswap, int_32, @TypeOf(int_64));
455 return @byteSwap(@TypeOf(int_32), int_32);530 }
456 } else {531}
457 return int_32;532
458 }533pub fn int32(need_bswap: bool, int_32: var, comptime Int64: var) Int64 {
534 if (need_bswap) {
535 return @byteSwap(@TypeOf(int_32), int_32);
536 } else {
537 return int_32;
459 }538 }
460}539}
461540
lib/std/zig/system.zig+16-1
...@@ -587,7 +587,6 @@ pub const NativeTargetInfo = struct {...@@ -587,7 +587,6 @@ pub const NativeTargetInfo = struct {
587 elf.ELFCLASS64 => true,587 elf.ELFCLASS64 => true,
588 else => return error.InvalidElfClass,588 else => return error.InvalidElfClass,
589 };589 };
590 const elfInt = elf.int;
591 var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);590 var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);
592 const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);591 const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);
593 const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);592 const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
...@@ -854,6 +853,22 @@ pub const NativeTargetInfo = struct {...@@ -854,6 +853,22 @@ pub const NativeTargetInfo = struct {
854 abi: Target.Abi,853 abi: Target.Abi,
855 };854 };
856855
856 pub fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
857 if (is_64) {
858 if (need_bswap) {
859 return @byteSwap(@TypeOf(int_64), int_64);
860 } else {
861 return int_64;
862 }
863 } else {
864 if (need_bswap) {
865 return @byteSwap(@TypeOf(int_32), int_32);
866 } else {
867 return int_32;
868 }
869 }
870 }
871
857 fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu {872 fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu {
858 // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,873 // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,
859 // although it is a runtime value, is guaranteed to be one of the architectures in the set874 // although it is a runtime value, is guaranteed to be one of the architectures in the set