#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */
typedef struct TYPE_9__ TYPE_3__;
typedef struct TYPE_8__ TYPE_2__;
typedef struct TYPE_7__ TYPE_1__;

/* Type definitions */
struct TYPE_9__ {
  int e_phoff;
  int e_phnum;
  int e_shoff;
  int e_shnum;
};
struct TYPE_8__ {
  scalar_t__ p_type;
  scalar_t__ p_filesz;
  scalar_t__ p_memsz;
  int p_offset;
  int p_vaddr;
  int p_flags;
};
struct TYPE_7__ {
  scalar_t__ sh_type;
  int sh_offset;
  size_t sh_link;
};
typedef int /*<<< orphan*/ Elf32_Sym;
typedef TYPE_1__ Elf32_Shdr;
typedef TYPE_2__ Elf32_Phdr;
typedef TYPE_3__ Elf32_Ehdr;

/* Variables and functions */
int MAP_ANONYMOUS;
int MAP_PRIVATE;
int PF_W;
int PF_X;
int PROT_EXEC;
int PROT_READ;
int PROT_WRITE;
scalar_t__ PT_LOAD;
scalar_t__ SHT_DYNSYM;
scalar_t__ SHT_REL;
void *find_sym(char *, TYPE_1__ *, char *, char *, char *);
int /*<<< orphan*/ is_image_valid(TYPE_3__ *);
int /*<<< orphan*/ memmove(char *, char *, scalar_t__);
int /*<<< orphan*/ memset(char *, int, unsigned int);
char *mmap(int /*<<< orphan*/ *, unsigned int, int, int, int /*<<< orphan*/,
           int /*<<< orphan*/);
int /*<<< orphan*/ mprotect(unsigned char *, scalar_t__, int);
int /*<<< orphan*/ munmap(char *, unsigned int);
int /*<<< orphan*/ printk(char *);
int /*<<< orphan*/ relocate(TYPE_1__ *, int /*<<< orphan*/ *, char *, char *,
                            char *);
void *image_load(char *elf_start, unsigned int size) {
  Elf32_Ehdr *hdr = NULL;
  Elf32_Phdr *phdr = NULL;
  Elf32_Shdr *shdr = NULL;
  Elf32_Sym *syms = NULL;
  char *strings = NULL;
  char *start = NULL;
  char *taddr = NULL;
  void *entry = NULL;
  int i = 0;
  char *exec = NULL;
  hdr = (Elf32_Ehdr *)elf_start;
  if (!is_image_valid(hdr)) {
    printk("image_load:: invalid ELF image\n");
    return 0;
  }
  exec = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
              MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
  if (!exec) {
    printk("image_load:: error allocating memory\n");
    return 0;
  }
  memset(exec, 0x0, size);
  phdr = (Elf32_Phdr *)(elf_start + hdr->e_phoff);
  for (i = 0; i < hdr->e_phnum; ++i) {
    if (phdr[i].p_type != PT_LOAD) {
      continue;
    }
    if (phdr[i].p_filesz > phdr[i].p_memsz) {
      printk("image_load:: p_filesz > p_memsz\n");
      munmap(exec, size);
      return 0;
    }
    if (!phdr[i].p_filesz) {
      continue;
    }
    start = elf_start + phdr[i].p_offset;
    taddr = phdr[i].p_vaddr + exec;
    memmove(taddr, start, phdr[i].p_filesz);
    if (!(phdr[i].p_flags & PF_W)) {
      mprotect((unsigned char *)taddr, phdr[i].p_memsz, PROT_READ);
    }
    if (phdr[i].p_flags & PF_X) {
      mprotect((unsigned char *)taddr, phdr[i].p_memsz, PROT_EXEC);
    }
  }
  shdr = (Elf32_Shdr *)(elf_start + hdr->e_shoff);
  for (i = 0; i < hdr->e_shnum; ++i) {
    if (shdr[i].sh_type == SHT_DYNSYM) {
      syms = (Elf32_Sym *)(elf_start + shdr[i].sh_offset);
      strings = elf_start + shdr[shdr[i].sh_link].sh_offset;
      entry = find_sym("main", shdr + i, strings, elf_start, exec);
      break;
    }
  }
  for (i = 0; i < hdr->e_shnum; ++i) {
    if (shdr[i].sh_type == SHT_REL) {
      relocate(shdr + i, syms, strings, elf_start, exec);
    }
  }
  return entry;
}


x86 assembly (clang, -O0):
<image_load>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
movq   $0x0,-0x20(%rbp)
movq   $0x0,-0x28(%rbp)
movq   $0x0,-0x30(%rbp)
movq   $0x0,-0x38(%rbp)
movq   $0x0,-0x40(%rbp)
movq   $0x0,-0x48(%rbp)
movq   $0x0,-0x50(%rbp)
movq   $0x0,-0x58(%rbp)
movl   $0x0,-0x5c(%rbp)
movq   $0x0,-0x68(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rdi
call   1080 <is_image_valid@plt>
cmp    $0x0,%eax
jne    1221 <image_load+0x91>
lea    0xdf1(%rip),%rdi
call   1030 <printk@plt>
movq   $0x0,-0x8(%rbp)
jmp    15a8 <image_load+0x418>
mov    -0x14(%rbp),%esi
mov    0x2dcd(%rip),%rax
mov    (%rax),%edx
mov    0x2d6c(%rip),%rax
or     (%rax),%edx
mov    0x2d83(%rip),%rax
or     (%rax),%edx
mov    0x2d52(%rip),%rax
mov    (%rax),%ecx
mov    0x2d79(%rip),%rax
or     (%rax),%ecx
xor    %eax,%eax
mov    %eax,%edi
xor    %r9d,%r9d
mov    %r9d,%r8d
call   1040 <mmap@plt>
mov    %rax,-0x68(%rbp)
cmpq   $0x0,-0x68(%rbp)
jne    1288 <image_load+0xf8>
lea    0xdaa(%rip),%rdi
call   1030 <printk@plt>
movq   $0x0,-0x8(%rbp)
jmp    15a8 <image_load+0x418>
mov    -0x68(%rbp),%rdi
mov    -0x14(%rbp),%edx
xor    %esi,%esi
call   1050 <memset@plt>
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%rcx
movslq (%rcx),%rcx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
movl   $0x0,-0x5c(%rbp)
mov    -0x5c(%rbp),%eax
mov    -0x20(%rbp),%rcx
cmp    0x4(%rcx),%eax
jge    1459 <image_load+0x2c9>
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    (%rax),%rax
mov    0x2cf8(%rip),%rcx
cmp    (%rcx),%rax
je     12e6 <image_load+0x156>
jmp    144b <image_load+0x2bb>
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x8(%rax),%rax
mov    -0x28(%rbp),%rcx
movslq -0x5c(%rbp),%rdx
imul   $0x28,%rdx,%rdx
add    %rdx,%rcx
cmp    0x10(%rcx),%rax
jle    1337 <image_load+0x1a7>
lea    0xd2d(%rip),%rdi
call   1030 <printk@plt>
mov    -0x68(%rbp),%rdi
mov    -0x14(%rbp),%esi
call   1090 <munmap@plt>
movq   $0x0,-0x8(%rbp)
jmp    15a8 <image_load+0x418>
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
cmpq   $0x0,0x8(%rax)
jne    1356 <image_load+0x1c6>
jmp    144b <image_load+0x2bb>
mov    -0x10(%rbp),%rax
mov    -0x28(%rbp),%rcx
movslq -0x5c(%rbp),%rdx
imul   $0x28,%rdx,%rdx
add    %rdx,%rcx
movslq 0x18(%rcx),%rcx
add    %rcx,%rax
mov    %rax,-0x48(%rbp)
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x1c(%rax),%ecx
mov    -0x68(%rbp),%rax
movslq %ecx,%rcx
add    %rcx,%rax
mov    %rax,-0x50(%rbp)
mov    -0x50(%rbp),%rdi
mov    -0x48(%rbp),%rsi
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x8(%rax),%rdx
call   10a0 <memmove@plt>
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x20(%rax),%eax
mov    0x2bdb(%rip),%rcx
and    (%rcx),%eax
cmp    $0x0,%eax
jne    13fd <image_load+0x26d>
mov    -0x50(%rbp),%rdi
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x10(%rax),%rsi
mov    0x2c02(%rip),%rax
mov    (%rax),%edx
call   10b0 <mprotect@plt>
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x20(%rax),%eax
mov    0x2bca(%rip),%rcx
and    (%rcx),%eax
cmp    $0x0,%eax
je     1446 <image_load+0x2b6>
mov    -0x50(%rbp),%rdi
mov    -0x28(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x28,%rcx,%rcx
add    %rcx,%rax
mov    0x10(%rax),%rsi
mov    0x2b81(%rip),%rax
mov    (%rax),%edx
call   10b0 <mprotect@plt>
jmp    144b <image_load+0x2bb>
mov    -0x5c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x5c(%rbp)
jmp    12af <image_load+0x11f>
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%rcx
movslq 0x8(%rcx),%rcx
add    %rcx,%rax
mov    %rax,-0x30(%rbp)
movl   $0x0,-0x5c(%rbp)
mov    -0x5c(%rbp),%eax
mov    -0x20(%rbp),%rcx
cmp    0xc(%rcx),%eax
jge    1530 <image_load+0x3a0>
mov    -0x30(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
mov    (%rax),%rax
mov    0x2b3c(%rip),%rcx
cmp    (%rcx),%rax
jne    151d <image_load+0x38d>
mov    -0x10(%rbp),%rax
mov    -0x30(%rbp),%rcx
movslq -0x5c(%rbp),%rdx
imul   $0x18,%rdx,%rdx
add    %rdx,%rcx
movslq 0x8(%rcx),%rcx
add    %rcx,%rax
mov    %rax,-0x38(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x30(%rbp),%rcx
mov    -0x30(%rbp),%rdx
movslq -0x5c(%rbp),%rsi
imul   $0x18,%rsi,%rsi
add    %rsi,%rdx
imul   $0x18,0x10(%rdx),%rdx
add    %rdx,%rcx
movslq 0x8(%rcx),%rcx
add    %rcx,%rax
mov    %rax,-0x40(%rbp)
mov    -0x30(%rbp),%rsi
movslq -0x5c(%rbp),%rax
imul   $0x18,%rax,%rax
add    %rax,%rsi
mov    -0x40(%rbp),%rdx
mov    -0x10(%rbp),%rcx
mov    -0x68(%rbp),%r8
lea    0xb58(%rip),%rdi
call   1070 <find_sym@plt>
mov    %rax,-0x58(%rbp)
jmp    1530 <image_load+0x3a0>
jmp    1522 <image_load+0x392>
mov    -0x5c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x5c(%rbp)
jmp    1473 <image_load+0x2e3>
movl   $0x0,-0x5c(%rbp)
mov    -0x5c(%rbp),%eax
mov    -0x20(%rbp),%rcx
cmp    0xc(%rcx),%eax
jge    15a0 <image_load+0x410>
mov    -0x30(%rbp),%rax
movslq -0x5c(%rbp),%rcx
imul   $0x18,%rcx,%rcx
add    %rcx,%rax
mov    (%rax),%rax
mov    0x2a58(%rip),%rcx
cmp    (%rcx),%rax
jne    158d <image_load+0x3fd>
mov    -0x30(%rbp),%rdi
movslq -0x5c(%rbp),%rax
imul   $0x18,%rax,%rax
add    %rax,%rdi
mov    -0x38(%rbp),%rsi
mov    -0x40(%rbp),%rdx
mov    -0x10(%rbp),%rcx
mov    -0x68(%rbp),%r8
call   1060 <relocate@plt>
jmp    1592 <image_load+0x402>
mov    -0x5c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x5c(%rbp)
jmp    1537 <image_load+0x3a7>
mov    -0x58(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<image_load>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %esi,%ebp
mov    %rdi,%rbx
call   1080 <is_image_valid@plt>
test   %eax,%eax
je     12cb <image_load+0x13b>
mov    0x2e44(%rip),%rcx
mov    0x2de5(%rip),%rax
mov    (%rax),%edx
or     (%rcx),%edx
mov    0x2dfa(%rip),%rax
or     (%rax),%edx
mov    0x2dc9(%rip),%rax
mov    0x2df2(%rip),%rcx
mov    (%rcx),%ecx
or     (%rax),%ecx
xor    %edi,%edi
mov    %ebp,%esi
xor    %r8d,%r8d
xor    %r9d,%r9d
call   1040 <mmap@plt>
test   %rax,%rax
je     131a <image_load+0x18a>
mov    %rax,%r14
mov    %rax,%rdi
xor    %esi,%esi
mov    %ebp,(%rsp)
mov    %ebp,%edx
call   1050 <memset@plt>
cmpl   $0x0,0x4(%rbx)
jle    12d4 <image_load+0x144>
movslq (%rbx),%rax
lea    (%rax,%rbx,1),%r12
add    $0x20,%r12
xor    %r13d,%r13d
mov    0x2dad(%rip),%r15
jmp    1245 <image_load+0xb5>
cs nopw 0x0(%rax,%rax,1)
nop
add    $0x1,%r13
movslq 0x4(%rbx),%rax
add    $0x28,%r12
cmp    %rax,%r13
jge    12d4 <image_load+0x144>
mov    -0x20(%r12),%rax
cmp    (%r15),%rax
jne    1230 <image_load+0xa0>
mov    -0x18(%r12),%rdx
cmp    -0x10(%r12),%rdx
jg     13c2 <image_load+0x232>
test   %rdx,%rdx
je     1230 <image_load+0xa0>
movslq -0x8(%r12),%rsi
add    %rbx,%rsi
movslq -0x4(%r12),%rbp
add    %r14,%rbp
mov    %rbp,%rdi
call   10a0 <memmove@plt>
mov    (%r12),%eax
mov    0x2d21(%rip),%rcx
test   %eax,(%rcx)
jne    12a5 <image_load+0x115>
mov    -0x10(%r12),%rsi
mov    0x2d61(%rip),%rax
mov    (%rax),%edx
mov    %rbp,%rdi
call   10b0 <mprotect@plt>
mov    (%r12),%eax
mov    0x2d34(%rip),%rcx
test   %eax,(%rcx)
je     1230 <image_load+0xa0>
mov    -0x10(%r12),%rsi
mov    0x2d04(%rip),%rax
mov    (%rax),%edx
mov    %rbp,%rdi
call   10b0 <mprotect@plt>
jmp    1230 <image_load+0xa0>
lea    0xd2e(%rip),%rdi
jmp    1321 <image_load+0x191>
mov    0xc(%rbx),%edi
test   %edi,%edi
jle    1326 <image_load+0x196>
movslq 0x8(%rbx),%rbp
add    %rbx,%rbp
mov    0x2cef(%rip),%rcx
mov    (%rcx),%rcx
xor    %r15d,%r15d
mov    %rdi,%rdx
mov    %rbp,%rsi
cs nopw 0x0(%rax,%rax,1)
nop
cmp    %rcx,(%rsi)
je     1337 <image_load+0x1a7>
add    $0x18,%rsi
add    $0xffffffffffffffff,%rdx
jne    1300 <image_load+0x170>
xor    %r13d,%r13d
xor    %eax,%eax
test   %edi,%edi
jg     136a <image_load+0x1da>
jmp    1328 <image_load+0x198>
lea    0xcff(%rip),%rdi
call   1030 <printk@plt>
xor    %eax,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
movslq 0x8(%rsi),%r15
add    %rbx,%r15
mov    0x10(%rsi),%rax
lea    (%rax,%rax,2),%rax
movslq 0x8(%rbp,%rax,8),%r13
add    %rbx,%r13
lea    0xd12(%rip),%rdi
mov    %r13,%rdx
mov    %rbx,%rcx
mov    %r14,%r8
call   1070 <find_sym@plt>
mov    0xc(%rbx),%edi
test   %edi,%edi
jle    1328 <image_load+0x198>
mov    %rax,(%rsp)
mov    0x2c43(%rip),%rax
mov    (%rax),%rcx
xor    %r12d,%r12d
jmp    1390 <image_load+0x200>
nopl   (%rax)
add    $0x1,%r12
movslq %edi,%rdx
add    $0x18,%rbp
cmp    %rdx,%r12
jge    13b9 <image_load+0x229>
cmp    %rcx,0x0(%rbp)
jne    1380 <image_load+0x1f0>
mov    %rbp,%rdi
mov    %r15,%rsi
mov    %r13,%rdx
mov    %rbx,%rcx
mov    %r14,%r8
call   1060 <relocate@plt>
mov    0x2c07(%rip),%rax
mov    (%rax),%rcx
mov    0xc(%rbx),%edi
jmp    1380 <image_load+0x1f0>
mov    (%rsp),%rax
jmp    1328 <image_load+0x198>
lea    0xc7d(%rip),%rdi
call   1030 <printk@plt>
mov    %r14,%rdi
mov    (%rsp),%esi
call   1090 <munmap@plt>
jmp    1326 <image_load+0x196>

LLVM IR (-O0):
%struct.TYPE_9__ = type { i32, i32, i32, i32 }
%struct.TYPE_8__ = type { i64, i64, i64, i32, i32, i32 }
%struct.TYPE_7__ = type { i64, i32, i64 }
@.str = [32 x i8] c"image_load:: invalid ELF image\0A\00"
@PROT_READ = global i32 0
@PROT_WRITE = global i32 0
@PROT_EXEC = global i32 0
@MAP_PRIVATE = global i32 0
@MAP_ANONYMOUS = global i32 0
@.str.1 = [38 x i8] c"image_load:: error allocating memory\0A\00"
@PT_LOAD = global i64 0
@.str.2 = [33 x i8] c"image_load:: p_filesz > p_memsz\0A\00"
@PF_W = global i32 0
@PF_X = global i32 0
@SHT_DYNSYM = global i64 0
@.str.3 = [5 x i8] c"main\00"
@SHT_REL = global i64 0
define i8* @image_load(i8* %0, i32 %1) {
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca i32
%6 = alloca %struct.TYPE_9__*
%7 = alloca %struct.TYPE_8__*
%8 = alloca %struct.TYPE_7__*
%9 = alloca i32*
%10 = alloca i8*
%11 = alloca i8*
%12 = alloca i8*
%13 = alloca i8*
%14 = alloca i32
%15 = alloca i8*
store i8* %0, i8** %4
store i32 %1, i32* %5
store %struct.TYPE_9__* null, %struct.TYPE_9__** %6
store %struct.TYPE_8__* null, %struct.TYPE_8__** %7
store %struct.TYPE_7__* null, %struct.TYPE_7__** %8
store i32* null, i32** %9
store i8* null, i8** %10
store i8* null, i8** %11
store i8* null, i8** %12
store i8* null, i8** %13
store i32 0, i32* %14
store i8* null, i8** %15
%16 = load i8*, i8** %4
%17 = bitcast i8* %16 to %struct.TYPE_9__*
store %struct.TYPE_9__* %17, %struct.TYPE_9__** %6
%18 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%19 = call i32 @is_image_valid(%struct.TYPE_9__* %18)
%20 = icmp ne i32 %19, 0
br i1 %20, label %23, label %21
21: ; preds = %2
%22 = call i32 @printk(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str, i64 0, i64 0))
store i8* null, i8** %3
br label %255
23: ; preds = %2
%24 = load i32, i32* %5
%25 = load i32, i32* @PROT_READ
%26 = load i32, i32* @PROT_WRITE
%27 = or i32 %25, %26
%28 = load i32, i32* @PROT_EXEC
%29 = or i32 %27, %28
%30 = load i32, i32* @MAP_PRIVATE
%31 = load i32, i32* @MAP_ANONYMOUS
%32 = or i32 %30, %31
%33 = call i8* @mmap(i32* null, i32 %24, i32 %29, i32 %32, i32 0, i32 0)
store i8* %33, i8** %15
%34 = load i8*, i8** %15
%35 = icmp ne i8* %34, null
br i1 %35, label %38, label %36
36: ; preds = %23
%37 = call i32 @printk(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.1, i64 0, i64 0))
store i8* null, i8** %3
br label %255
38: ; preds = %23
%39 = load i8*, i8** %15
%40 = load i32, i32* %5
%41 = call i32 @memset(i8* %39, i32 0, i32 %40)
%42 = load i8*, i8** %4
%43 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%44 = getelementptr inbounds %struct.TYPE_9__, %struct.TYPE_9__* %43, i32 0, i32 0
%45 = load i32, i32* %44
%46 = sext i32 %45 to i64
%47 = getelementptr inbounds i8, i8* %42, i64 %46
%48 = bitcast i8* %47 to %struct.TYPE_8__*
store %struct.TYPE_8__* %48, %struct.TYPE_8__** %7
store i32 0, i32* %14
br label %49
49: ; preds = %161, %38
%50 = load i32, i32* %14
%51 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%52 = getelementptr inbounds %struct.TYPE_9__, %struct.TYPE_9__* %51, i32 0, i32 1
%53 = load i32, i32* %52
%54 = icmp slt i32 %50, %53
br i1 %54, label %55, label %164
55: ; preds = %49
%56 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%57 = load i32, i32* %14
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %56, i64 %58
%60 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %59, i32 0, i32 0
%61 = load i64, i64* %60
%62 = load i64, i64* @PT_LOAD
%63 = icmp ne i64 %61, %62
br i1 %63, label %64, label %65
64: ; preds = %55
br label %161
65: ; preds = %55
%66 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%67 = load i32, i32* %14
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %66, i64 %68
%70 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %69, i32 0, i32 1
%71 = load i64, i64* %70
%72 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%73 = load i32, i32* %14
%74 = sext i32 %73 to i64
%75 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %72, i64 %74
%76 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %75, i32 0, i32 2
%77 = load i64, i64* %76
%78 = icmp sgt i64 %71, %77
br i1 %78, label %79, label %84
79: ; preds = %65
%80 = call i32 @printk(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
%81 = load i8*, i8** %15
%82 = load i32, i32* %5
%83 = call i32 @munmap(i8* %81, i32 %82)
store i8* null, i8** %3
br label %255
84: ; preds = %65
%85 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%86 = load i32, i32* %14
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %85, i64 %87
%89 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %88, i32 0, i32 1
%90 = load i64, i64* %89
%91 = icmp ne i64 %90, 0
br i1 %91, label %93, label %92
92: ; preds = %84
br label %161
93: ; preds = %84
%94 = load i8*, i8** %4
%95 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%96 = load i32, i32* %14
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %95, i64 %97
%99 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %98, i32 0, i32 3
%100 = load i32, i32* %99
%101 = sext i32 %100 to i64
%102 = getelementptr inbounds i8, i8* %94, i64 %101
store i8* %102, i8** %11
%103 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%104 = load i32, i32* %14
%105 = sext i32 %104 to i64
%106 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %103, i64 %105
%107 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %106, i32 0, i32 4
%108 = load i32, i32* %107
%109 = load i8*, i8** %15
%110 = sext i32 %108 to i64
%111 = getelementptr inbounds i8, i8* %109, i64 %110
store i8* %111, i8** %12
%112 = load i8*, i8** %12
%113 = load i8*, i8** %11
%114 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%115 = load i32, i32* %14
%116 = sext i32 %115 to i64
%117 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %114, i64 %116
%118 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %117, i32 0, i32 1
%119 = load i64, i64* %118
%120 = call i32 @memmove(i8* %112, i8* %113, i64 %119)
%121 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%122 = load i32, i32* %14
%123 = sext i32 %122 to i64
%124 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %121, i64 %123
%125 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %124, i32 0, i32 5
%126 = load i32, i32* %125
%127 = load i32, i32* @PF_W
%128 = and i32 %126, %127
%129 = icmp ne i32 %128, 0
br i1 %129, label %140, label %130
130: ; preds = %93
%131 = load i8*, i8** %12
%132 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%133 = load i32, i32* %14
%134 = sext i32 %133 to i64
%135 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %132, i64 %134
%136 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %135, i32 0, i32 2
%137 = load i64, i64* %136
%138 = load i32, i32* @PROT_READ
%139 = call i32 @mprotect(i8* %131, i64 %137, i32 %138)
br label %140
140: ; preds = %130, %93
%141 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%142 = load i32, i32* %14
%143 = sext i32 %142 to i64
%144 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %141, i64 %143
%145 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %144, i32 0, i32 5
%146 = load i32, i32* %145
%147 = load i32, i32* @PF_X
%148 = and i32 %146, %147
%149 = icmp ne i32 %148, 0
br i1 %149, label %150, label %160
150: ; preds = %140
%151 = load i8*, i8** %12
%152 = load %struct.TYPE_8__*, %struct.TYPE_8__** %7
%153 = load i32, i32* %14
%154 = sext i32 %153 to i64
%155 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %152, i64 %154
%156 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %155, i32 0, i32 2
%157 = load i64, i64* %156
%158 = load i32, i32* @PROT_EXEC
%159 = call i32 @mprotect(i8* %151, i64 %157, i32 %158)
br label %160
160: ; preds = %150, %140
br label %161
161: ; preds = %160, %92, %64
%162 = load i32, i32* %14
%163 = add nsw i32 %162, 1
store i32 %163, i32* %14
br label %49
164: ; preds = %49
%165 = load i8*, i8** %4
%166 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%167 = getelementptr inbounds %struct.TYPE_9__, %struct.TYPE_9__* %166, i32 0, i32 2
%168 = load i32, i32* %167
%169 = sext i32 %168 to i64
%170 = getelementptr inbounds i8, i8* %165, i64 %169
%171 = bitcast i8* %170 to %struct.TYPE_7__*
store %struct.TYPE_7__* %171, %struct.TYPE_7__** %8
store i32 0, i32* %14
br label %172
172: ; preds = %220, %164
%173 = load i32, i32* %14
%174 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%175 = getelementptr inbounds %struct.TYPE_9__, %struct.TYPE_9__* %174, i32 0, i32 3
%176 = load i32, i32* %175
%177 = icmp slt i32 %173, %176
br i1 %177, label %178, label %223
178: ; preds = %172
%179 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%180 = load i32, i32* %14
%181 = sext i32 %180 to i64
%182 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %179, i64 %181
%183 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %182, i32 0, i32 0
%184 = load i64, i64* %183
%185 = load i64, i64* @SHT_DYNSYM
%186 = icmp eq i64 %184, %185
br i1 %186, label %187, label %219
187: ; preds = %178
%188 = load i8*, i8** %4
%189 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%190 = load i32, i32* %14
%191 = sext i32 %190 to i64
%192 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %189, i64 %191
%193 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %192, i32 0, i32 1
%194 = load i32, i32* %193
%195 = sext i32 %194 to i64
%196 = getelementptr inbounds i8, i8* %188, i64 %195
%197 = bitcast i8* %196 to i32*
store i32* %197, i32** %9
%198 = load i8*, i8** %4
%199 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%200 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%201 = load i32, i32* %14
%202 = sext i32 %201 to i64
%203 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %200, i64 %202
%204 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %203, i32 0, i32 2
%205 = load i64, i64* %204
%206 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %199, i64 %205
%207 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %206, i32 0, i32 1
%208 = load i32, i32* %207
%209 = sext i32 %208 to i64
%210 = getelementptr inbounds i8, i8* %198, i64 %209
store i8* %210, i8** %10
%211 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%212 = load i32, i32* %14
%213 = sext i32 %212 to i64
%214 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %211, i64 %213
%215 = load i8*, i8** %10
%216 = load i8*, i8** %4
%217 = load i8*, i8** %15
%218 = call i8* @find_sym(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0), %struct.TYPE_7__* %214, i8* %215, i8* %216, i8* %217)
store i8* %218, i8** %13
br label %223
219: ; preds = %178
br label %220
220: ; preds = %219
%221 = load i32, i32* %14
%222 = add nsw i32 %221, 1
store i32 %222, i32* %14
br label %172
223: ; preds = %187, %172
store i32 0, i32* %14
br label %224
224: ; preds = %250, %223
%225 = load i32, i32* %14
%226 = load %struct.TYPE_9__*, %struct.TYPE_9__** %6
%227 = getelementptr inbounds %struct.TYPE_9__, %struct.TYPE_9__* %226, i32 0, i32 3
%228 = load i32, i32* %227
%229 = icmp slt i32 %225, %228
br i1 %229, label %230, label %253
230: ; preds = %224
%231 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%232 = load i32, i32* %14
%233 = sext i32 %232 to i64
%234 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %231, i64 %233
%235 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %234, i32 0, i32 0
%236 = load i64, i64* %235
%237 = load i64, i64* @SHT_REL
%238 = icmp eq i64 %236, %237
br i1 %238, label %239, label %249
239: ; preds = %230
%240 = load %struct.TYPE_7__*, %struct.TYPE_7__** %8
%241 = load i32, i32* %14
%242 = sext i32 %241 to i64
%243 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %240, i64 %242
%244 = load i32*, i32** %9
%245 = load i8*, i8** %10
%246 = load i8*, i8** %4
%247 = load i8*, i8** %15
%248 = call i32 @relocate(%struct.TYPE_7__* %243, i32* %244, i8* %245, i8* %246, i8* %247)
br label %249
249: ; preds = %239, %230
br label %250
250: ; preds = %249
%251 = load i32, i32* %14
%252 = add nsw i32 %251, 1
store i32 %252, i32* %14
br label %224
253: ; preds = %224
%254 = load i8*, i8** %13
store i8* %254, i8** %3
br label %255
255: ; preds = %253, %79, %36, %21
%256 = load i8*, i8** %3
ret i8* %256
}

LLVM IR (-O2):
%struct.TYPE_9__ = type { i32, i32, i32, i32 }
%struct.TYPE_8__ = type { i64, i64, i64, i32, i32, i32 }
%struct.TYPE_7__ = type { i64, i32, i64 }
@.str = [32 x i8] c"image_load:: invalid ELF image\0A\00"
@PROT_READ = global i32 0
@PROT_WRITE = global i32 0
@PROT_EXEC = global i32 0
@MAP_PRIVATE = global i32 0
@MAP_ANONYMOUS = global i32 0
@.str.1 = [38 x i8] c"image_load:: error allocating memory\0A\00"
@PT_LOAD = global i64 0
@.str.2 = [33 x i8] c"image_load:: p_filesz > p_memsz\0A\00"
@PF_W = global i32 0
@PF_X = global i32 0
@SHT_DYNSYM = global i64 0
@.str.3 = [5 x i8] c"main\00"
@SHT_REL = global i64 0
define i8* @image_load(i8* %0, i32 %1) {
%3 = bitcast i8* %0 to %struct.TYPE_9__*
%4 = tail call i32 @is_image_valid(%struct.TYPE_9__* %3)
%5 = icmp eq i32 %4, 0
br i1 %5, label %6, label %8
6: ; preds = %2
%7 = tail call i32 @printk(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str, i64 0, i64 0))
br label %147
8: ; preds = %2
%9 = load i32, i32* @PROT_READ
%10 = load i32, i32* @PROT_WRITE
%11 = or i32 %10, %9
%12 = load i32, i32* @PROT_EXEC
%13 = or i32 %11, %12
%14 = load i32, i32* @MAP_PRIVATE
%15 = load i32, i32* @MAP_ANONYMOUS
%16 = or i32 %15, %14
%17 = tail call i8* @mmap(i32* null, i32 %1, i32 %13, i32 %16, i32 0, i32 0)
%18 = icmp eq i8* %17, null
br i1 %18, label %19, label %21
19: ; preds = %8
%20 = tail call i32 @printk(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.1, i64 0, i64 0))
br label %147
21: ; preds = %8
%22 = tail call i32 @memset(i8* %17, i32 0, i32 %1)
%23 = bitcast i8* %0 to i32*
%24 = load i32, i32* %23
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds i8, i8* %0, i64 %25
%27 = bitcast i8* %26 to %struct.TYPE_8__*
%28 = getelementptr inbounds i8, i8* %0, i64 4
%29 = bitcast i8* %28 to i32*
%30 = load i32, i32* %29
%31 = icmp sgt i32 %30, 0
br i1 %31, label %32, label %83
32: ; preds = %21, %78
%33 = phi i64 [ %79, %78 ], [ 0, %21 ]
%34 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 0
%35 = load i64, i64* %34
%36 = load i64, i64* @PT_LOAD
%37 = icmp eq i64 %35, %36
br i1 %37, label %38, label %78
38: ; preds = %32
%39 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 1
%40 = load i64, i64* %39
%41 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 2
%42 = load i64, i64* %41
%43 = icmp sgt i64 %40, %42
br i1 %43, label %44, label %47
44: ; preds = %38
%45 = tail call i32 @printk(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
%46 = tail call i32 @munmap(i8* %17, i32 %1)
br label %147
47: ; preds = %38
%48 = icmp eq i64 %40, 0
br i1 %48, label %78, label %49
49: ; preds = %47
%50 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 3
%51 = load i32, i32* %50
%52 = sext i32 %51 to i64
%53 = getelementptr inbounds i8, i8* %0, i64 %52
%54 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 4
%55 = load i32, i32* %54
%56 = sext i32 %55 to i64
%57 = getelementptr inbounds i8, i8* %17, i64 %56
%58 = tail call i32 @memmove(i8* %57, i8* %53, i64 %40)
%59 = getelementptr inbounds %struct.TYPE_8__, %struct.TYPE_8__* %27, i64 %33, i32 5
%60 = load i32, i32* %59
%61 = load i32, i32* @PF_W
%62 = and i32 %61, %60
%63 = icmp eq i32 %62, 0
br i1 %63, label %64, label %69
64: ; preds = %49
%65 = load i64, i64* %41
%66 = load i32, i32* @PROT_READ
%67 = tail call i32 @mprotect(i8* %57, i64 %65, i32 %66)
%68 = load i32, i32* %59
br label %69
69: ; preds = %64, %49
%70 = phi i32 [ %68, %64 ], [ %60, %49 ]
%71 = load i32, i32* @PF_X
%72 = and i32 %71, %70
%73 = icmp eq i32 %72, 0
br i1 %73, label %78, label %74
74: ; preds = %69
%75 = load i64, i64* %41
%76 = load i32, i32* @PROT_EXEC
%77 = tail call i32 @mprotect(i8* %57, i64 %75, i32 %76)
br label %78
78: ; preds = %69, %74, %47, %32
%79 = add nuw nsw i64 %33, 1
%80 = load i32, i32* %29
%81 = sext i32 %80 to i64
%82 = icmp slt i64 %79, %81
br i1 %82, label %32, label %83
83: ; preds = %78, %21
%84 = getelementptr inbounds i8, i8* %0, i64 8
%85 = bitcast i8* %84 to i32*
%86 = load i32, i32* %85
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds i8, i8* %0, i64 %87
%89 = bitcast i8* %88 to %struct.TYPE_7__*
%90 = getelementptr inbounds i8, i8* %0, i64 12
%91 = bitcast i8* %90 to i32*
%92 = load i32, i32* %91
%93 = icmp sgt i32 %92, 0
br i1 %93, label %94, label %147
94: ; preds = %83
%95 = load i64, i64* @SHT_DYNSYM
%96 = zext i32 %92 to i64
br label %97
97: ; preds = %94, %118
%98 = phi i64 [ 0, %94 ], [ %119, %118 ]
%99 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %89, i64 %98
%100 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %99, i64 0, i32 0
%101 = load i64, i64* %100
%102 = icmp eq i64 %101, %95
br i1 %102, label %103, label %118
103: ; preds = %97
%104 = and i64 %98, 4294967295
%105 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %89, i64 %104, i32 1
%106 = load i32, i32* %105
%107 = sext i32 %106 to i64
%108 = getelementptr inbounds i8, i8* %0, i64 %107
%109 = bitcast i8* %108 to i32*
%110 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %89, i64 %104, i32 2
%111 = load i64, i64* %110
%112 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %89, i64 %111, i32 1
%113 = load i32, i32* %112
%114 = sext i32 %113 to i64
%115 = getelementptr inbounds i8, i8* %0, i64 %114
%116 = tail call i8* @find_sym(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0), %struct.TYPE_7__* %99, i8* %115, i8* %0, i8* %17)
%117 = load i32, i32* %91
br label %121
118: ; preds = %97
%119 = add nuw nsw i64 %98, 1
%120 = icmp eq i64 %119, %96
br i1 %120, label %121, label %97
121: ; preds = %118, %103
%122 = phi i32 [ %117, %103 ], [ %92, %118 ]
%123 = phi i32* [ %109, %103 ], [ null, %118 ]
%124 = phi i8* [ %115, %103 ], [ null, %118 ]
%125 = phi i8* [ %116, %103 ], [ null, %118 ]
%126 = icmp sgt i32 %122, 0
br i1 %126, label %127, label %147
127: ; preds = %121
%128 = load i64, i64* @SHT_REL
br label %129
129: ; preds = %127, %141
%130 = phi i32 [ %122, %127 ], [ %142, %141 ]
%131 = phi i64 [ %128, %127 ], [ %143, %141 ]
%132 = phi i64 [ 0, %127 ], [ %144, %141 ]
%133 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %89, i64 %132
%134 = getelementptr inbounds %struct.TYPE_7__, %struct.TYPE_7__* %133, i64 0, i32 0
%135 = load i64, i64* %134
%136 = icmp eq i64 %135, %131
br i1 %136, label %137, label %141
137: ; preds = %129
%138 = tail call i32 @relocate(%struct.TYPE_7__* %133, i32* %123, i8* %124, i8* %0, i8* %17)
%139 = load i64, i64* @SHT_REL
%140 = load i32, i32* %91
br label %141
141: ; preds = %129, %137
%142 = phi i32 [ %130, %129 ], [ %140, %137 ]
%143 = phi i64 [ %131, %129 ], [ %139, %137 ]
%144 = add nuw nsw i64 %132, 1
%145 = sext i32 %142 to i64
%146 = icmp slt i64 %144, %145
br i1 %146, label %129, label %147
147: ; preds = %141, %83, %121, %44, %19, %6
%148 = phi i8* [ null, %44 ], [ null, %19 ], [ null, %6 ], [ %125, %121 ], [ null, %83 ], [ %125, %141 ]
ret i8* %148
}