diff --git a/hw/an5206.c b/hw/an5206.c
index b9f19a9..1797337 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -68,7 +68,7 @@ static void an5206_init(ram_addr_t ram_size,
         exit(1);
     }
 
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+    kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
                            NULL, NULL, 1, ELF_MACHINE, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 620550b..54bd9f5 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -226,7 +226,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
 #endif
 
     /* Assume that raw images are linux kernels, and ELF images are not.  */
-    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+    kernel_size = load_elf(info->kernel_filename, NULL, &elf_entry,
                            NULL, NULL, big_endian, ELF_MACHINE, 1);
     entry = elf_entry;
     if (kernel_size < 0) {
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 588ec98..57a1515 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -222,7 +222,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
     big_endian = 0;
 #endif
 
-    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+    image_size = load_elf(kernel_filename, NULL, &entry, &lowaddr,
                           NULL, big_endian, ELF_MACHINE, 1);
     if (image_size < 0) {
         image_size = load_image_targphys(kernel_filename, 0, flash_size);
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index 2ef17f6..b6eec35 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -66,11 +66,13 @@ void cris_load_image(CPUState *env, struct cris_load_info *li)
     uint64_t entry, high;
     int kcmdline_len;
     int image_size;
+    ElfHandlers handlers = elf_default_handlers;
 
     env->load_info = li;
     /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
        devboard SDK.  */
-    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+    handlers.translate_fn = translate_kernel_address;
+    image_size = load_elf(li->image_filename, &handlers,
                           &entry, NULL, &high, 0, ELF_MACHINE, 0);
     li->entry = entry;
     if (image_size < 0) {
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 61efb39..db49e31 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -43,7 +43,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
 
     /* Load kernel.  */
     if (kernel_filename) {
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+        kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
                                NULL, NULL, 1, ELF_MACHINE, 0);
         entry = elf_entry;
         if (kernel_size < 0) {
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 0bd7235..8b63dfc 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -190,8 +190,7 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
 }
 
 static int glue(load_elf, SZ)(const char *name, int fd,
-                              uint64_t (*translate_fn)(void *, uint64_t),
-                              void *translate_opaque,
+                              ElfHandlers *handlers,
                               int must_swab, uint64_t *pentry,
                               uint64_t *lowaddr, uint64_t *highaddr,
                               int elf_machine, int clear_lsb)
@@ -265,11 +264,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
             }
             /* address_offset is hack for kernel images that are
                linked at the wrong physical address.  */
-            if (translate_fn) {
-                addr = translate_fn(translate_opaque, ph->p_paddr);
-            } else {
-                addr = ph->p_paddr;
-            }
+            addr = handlers->translate_fn(handlers->translate_opaque,
+                                          ph->p_paddr);
 
             snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
             rom_add_blob_fixed(label, data, mem_size, addr);
diff --git a/hw/loader.c b/hw/loader.c
index 49ac1fa..50b43a0 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -229,6 +229,17 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
 
 /* ELF loader */
 
+static uint64_t elf_default_translate(void *opaque, uint64_t addr)
+{
+    return addr;
+}
+
+ElfHandlers elf_default_handlers = {
+    .translate_fn = elf_default_translate,
+    .translate_opaque = NULL,
+};
+
+
 static void *load_at(int fd, int offset, int size)
 {
     void *ptr;
@@ -276,9 +287,9 @@ static void *load_at(int fd, int offset, int size)
 #include "elf_ops.h"
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
-             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-             uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
+int load_elf(const char *filename, ElfHandlers *handlers,
+             uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
+             int big_endian, int elf_machine, int clear_lsb)
 {
     int fd, data_order, target_data_order, must_swab, ret;
     uint8_t e_ident[EI_NIDENT];
@@ -310,13 +321,17 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
     if (target_data_order != e_ident[EI_DATA])
         return -1;
 
+    if (!handlers) {
+        handlers = &elf_default_handlers;
+    }
+
     lseek(fd, 0, SEEK_SET);
     if (e_ident[EI_CLASS] == ELFCLASS64) {
-        ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+        ret = load_elf64(filename, fd, handlers, must_swab, pentry, lowaddr,
+                         highaddr, elf_machine, clear_lsb);
     } else {
-        ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+        ret = load_elf32(filename, fd, handlers, must_swab, pentry, lowaddr,
+                         highaddr, elf_machine, clear_lsb);
     }
 
     close(fd);
diff --git a/hw/loader.h b/hw/loader.h
index 1f82fc5..27a2c36 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -5,10 +5,18 @@
 int get_image_size(const char *filename);
 int load_image(const char *filename, uint8_t *addr); /* deprecated */
 int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
-             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-             uint64_t *highaddr, int big_endian, int elf_machine,
-             int clear_lsb);
+
+typedef struct ElfHandlers {
+    uint64_t (*translate_fn)(void *opaque, uint64_t address);
+    void *translate_opaque;
+} ElfHandlers;
+
+extern ElfHandlers elf_default_handlers;
+
+int load_elf(const char *filename, ElfHandlers *handlers,
+             uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
+             int big_endian, int elf_machine, int clear_lsb);
+
 int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
               int bswap_needed, target_phys_addr_t target_page_size);
 int load_uimage(const char *filename, target_phys_addr_t *ep,
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 38645f7..3a27574 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -270,7 +270,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
         exit(1);
     }
 
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+    kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
                            NULL, NULL, 1, ELF_MACHINE, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 07eb9ee..5e259c6 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -106,8 +106,10 @@ static int64_t load_kernel (CPUState *env)
     ram_addr_t initrd_offset;
     uint32_t *prom_buf;
     long prom_size;
+    ElfHandlers handlers = elf_default_handlers;
 
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+    handlers.translate_fn = cpu_mips_kseg0_to_phys;
+    if (load_elf(loaderparams.kernel_filename, &handlers,
                  (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
                  (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 8026071..42da041 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -686,6 +686,7 @@ static int64_t load_kernel (void)
     uint32_t *prom_buf;
     long prom_size;
     int prom_index = 0;
+    ElfHandlers handlers = elf_default_handlers;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -693,7 +694,8 @@ static int64_t load_kernel (void)
     big_endian = 0;
 #endif
 
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+    handlers.translate_fn = cpu_mips_kseg0_to_phys;
+    if (load_elf(loaderparams.kernel_filename, &handlers,
                  (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
                  big_endian, ELF_MACHINE, 1) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 111c759..55bfc25 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -55,6 +55,7 @@ static int64_t load_kernel(void)
     long initrd_size;
     ram_addr_t initrd_offset;
     int big_endian;
+    ElfHandlers handlers = elf_default_handlers;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
@@ -62,8 +63,9 @@ static int64_t load_kernel(void)
     big_endian = 0;
 #endif
 
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
+    handlers.translate_fn = cpu_mips_kseg0_to_phys;
+    kernel_size = load_elf(loaderparams.kernel_filename, &handlers,
+                           (uint64_t *)&entry, NULL,
                            (uint64_t *)&kernel_high, big_endian,
                            ELF_MACHINE, 1);
     if (kernel_size >= 0) {
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index aa34890..bd5f340 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -81,14 +81,16 @@ static int64_t load_kernel(void)
     ram_addr_t initrd_offset;
     uint32_t *params_buf;
     int big_endian;
+    ElfHandlers handlers = elf_default_handlers;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     big_endian = 1;
 #else
     big_endian = 0;
 #endif
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
+    handlers.translate_fn = cpu_mips_kseg0_to_phys;
+    kernel_size = load_elf(loaderparams.kernel_filename, &handlers,
+                           (uint64_t *)&entry, NULL,
                            (uint64_t *)&kernel_high, big_endian,
                            ELF_MACHINE, 1);
     if (kernel_size >= 0) {
diff --git a/hw/multiboot.c b/hw/multiboot.c
index f9097a2..97b891a 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -171,7 +171,7 @@ int load_multiboot(void *fw_cfg,
         uint64_t elf_low, elf_high;
         int kernel_size;
         fclose(f);
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+        kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
                                &elf_low, &elf_high, 0, ELF_MACHINE, 0);
         if (kernel_size < 0) {
             fprintf(stderr, "Error while loading elf kernel\n");
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 42de459..6a5416e 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -167,15 +167,17 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     if (kernel_filename) {
         uint64_t entry, low, high;
         uint32_t base32;
+        ElfHandlers handlers = elf_default_handlers;
 
         /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
+        kernel_size = load_elf(kernel_filename, NULL,
                                &entry, &low, &high,
                                1, ELF_MACHINE, 0);
         base32 = entry;
         if (base32 == 0xc0000000) {
-            kernel_size = load_elf(kernel_filename, translate_kernel_address,
-                                   NULL, &entry, NULL, NULL,
+            handlers.translate_fn = translate_kernel_address;
+            kernel_size = load_elf(kernel_filename, &handlers,
+                                   &entry, NULL, NULL,
                                    1, ELF_MACHINE, 0);
         }
         /* Always boot into physical ram.  */
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 34ddf45..8616700 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -123,7 +123,7 @@ static void bamboo_init(ram_addr_t ram_size,
     if (kernel_filename) {
         success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
         if (success < 0) {
-            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+            success = load_elf(kernel_filename, NULL, &elf_entry,
                                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
             entry = elf_entry;
             loadaddr = elf_lowaddr;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 4369337..f479289 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -181,7 +181,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
 
     /* Load OpenBIOS (ELF) */
     if (filename) {
-        bios_size = load_elf(filename, NULL, NULL, NULL,
+        bios_size = load_elf(filename, NULL, NULL,
                              NULL, NULL, 1, ELF_MACHINE, 0);
 
         qemu_free(filename);
@@ -196,6 +196,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     if (linux_boot) {
         uint64_t lowaddr = 0;
         int bswap_needed;
+        ElfHandlers handlers = elf_default_handlers;
 
 #ifdef BSWAP_NEEDED
         bswap_needed = 1;
@@ -204,7 +205,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
 #endif
         kernel_base = KERNEL_LOAD_ADDR;
 
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+        handlers.translate_fn = translate_kernel_address;
+        kernel_size = load_elf(kernel_filename, &handlers,
                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index a2f9ddf..f24bded 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -119,7 +119,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
 
     /* Load OpenBIOS (ELF) */
     if (filename) {
-        bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+        bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
                              1, ELF_MACHINE, 0);
         qemu_free(filename);
     } else {
@@ -133,14 +133,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     if (linux_boot) {
         uint64_t lowaddr = 0;
         int bswap_needed;
+        ElfHandlers handlers = elf_default_handlers;
 
 #ifdef BSWAP_NEEDED
         bswap_needed = 1;
 #else
         bswap_needed = 0;
 #endif
+        handlers.translate_fn = translate_kernel_address;
         kernel_base = KERNEL_LOAD_ADDR;
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+        kernel_size = load_elf(kernel_filename, &handlers,
                                NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 59d20d3..1d066ab 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -233,7 +233,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     if (kernel_filename) {
         kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
         if (kernel_size < 0) {
-            kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+            kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
                                    &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
             entry = elf_entry;
             loadaddr = elf_lowaddr;
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 0392109..265ac49 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -322,13 +322,15 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
     kernel_size = 0;
     if (linux_boot) {
         int bswap_needed;
+        ElfHandlers handlers = elf_default_handlers;
 
 #ifdef BSWAP_NEEDED
         bswap_needed = 1;
 #else
         bswap_needed = 0;
 #endif
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+        handlers.translate_fn = translate_kernel_address;
+        kernel_size = load_elf(kernel_filename, &handlers,
                                NULL, NULL, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
@@ -677,7 +679,11 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
     }
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr, NULL,
+        ElfHandlers handlers = elf_default_handlers;
+
+        handlers.translate_fn = translate_prom_address;
+        handlers.translate_opaque = &addr;
+        ret = load_elf(filename, &handlers, NULL,
                        NULL, NULL, 1, ELF_MACHINE, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 45a46d6..b07c1e1 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -194,7 +194,7 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
 #else
         bswap_needed = 0;
 #endif
-        kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
                                NULL, NULL, 1, ELF_MACHINE, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
@@ -597,6 +597,7 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
     SysBusDevice *s;
     char *filename;
     int ret;
+    ElfHandlers handlers = elf_default_handlers;
 
     dev = qdev_create(NULL, "openprom");
     qdev_init_nofail(dev);
@@ -610,7 +611,9 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
     }
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr,
+        handlers.translate_fn = translate_prom_address;
+        handlers.translate_opaque = &addr;
+        ret = load_elf(filename, &handlers,
                        NULL, NULL, NULL, 1, ELF_MACHINE, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index fa60515..3ef7487 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -238,7 +238,7 @@ static void virtex_init(ram_addr_t ram_size,
         target_phys_addr_t boot_offset;
 
         /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
+        kernel_size = load_elf(kernel_filename, NULL,
                                &entry, &low, &high, 1, ELF_MACHINE, 0);
         boot_info.bootstrap_pc = entry & 0x00ffffff;
 
