--- distcc-trunk.orig/src/fix_debug_info.c	2010-02-04 09:17:51.000000000 -0600
+++ distcc-trunk.new/src/fix_debug_info.c	2010-02-04 09:30:52.000000000 -0600
@@ -53,6 +53,42 @@
 #endif
 
 #ifdef HAVE_ELF_H
+
+static uint16_t elf_bswap_16(uint16_t halfword)
+{
+    return (halfword >> 8) | (halfword << 8);
+}
+
+static uint32_t elf_bswap_32(uint32_t word)
+{
+    return ((uint32_t)elf_bswap_16(word & 0xffff) << 16) | (elf_bswap_16(word >> 16));
+}
+
+static uint64_t elf_bswap_64(uint64_t xword)
+{
+    return ((uint64_t)elf_bswap_32(xword & 0xffffffffULL) << 32) | (elf_bswap_32(xword >> 32));
+}
+
+
+
+#define GET_ELF32_HALF(loc, byteswap)   (Elf32_Half)    ((byteswap) ? elf_bswap_16(loc) : loc)
+#define GET_ELF32_WORD(loc, byteswap)   (Elf32_Word)    ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF32_SWORD(loc, byteswap)  (Elf32_Sword)   ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF32_XWORD(loc, byteswap)  (Elf32_Xword)   ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF32_SXWORD(loc, byteswap) (Elf32_Sxword)  ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF32_ADDR(loc, byteswap)   (Elf32_Addr)    ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF32_OFFSET(loc, byteswap) (Elf32_Off)     ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF32_VERSYM(loc, byteswap) (Elf32_Versym)  ((byteswap) ? elf_bswap_16(loc) : loc)
+
+#define GET_ELF64_HALF(loc, byteswap)   (Elf64_Half)    ((byteswap) ? elf_bswap_16(loc) : loc)
+#define GET_ELF64_WORD(loc, byteswap)   (Elf64_Word)    ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF64_SWORD(loc, byteswap)  (Elf64_Sword)   ((byteswap) ? elf_bswap_32(loc) : loc)
+#define GET_ELF64_XWORD(loc, byteswap)  (Elf64_Xword)   ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF64_SXWORD(loc, byteswap) (Elf64_Sxword)  ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF64_ADDR(loc, byteswap)   (Elf64_Addr)    ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF64_OFFSET(loc, byteswap) (Elf64_Off)     ((byteswap) ? elf_bswap_64(loc) : loc)
+#define GET_ELF64_VERSYM(loc, byteswap) (Elf64_Versym)  ((byteswap) ? elf_bswap_16(loc) : loc)
+
 /*
  * Search for an ELF section of the specified name and type.
  * Given an ELF file that has been mmapped (or read) into memory starting
@@ -68,6 +104,7 @@
   const Elf32_Ehdr *elf32_header = (const Elf32_Ehdr *) (const void *) elf_base;
   unsigned int i;
   unsigned int num_sections;
+  unsigned int byteswap = 0;
 
   assert(elf_mapped_base);
   assert(section_start);
@@ -102,22 +139,17 @@
    * enddianness, because ELF header fields use the same endianness
    * as the target computer.  When cross-compiling to a target with
    * a different endianness, we would need to byte-swap all the fields
-   * that we use.  Right now we don't handle that case.
-   *
-   * TODO(fergus):
-   * handle object files with different endianness than the host.
+   * that we use.
    */
 #if WORDS_BIGENDIAN
   if (elf32_header->e_ident[EI_DATA] != ELFDATA2MSB) {
-    rs_trace("sorry, not fixing debug info: "
-            "distcc server host is big-endian, object file is not");
-    return 0;
+    rs_trace("distcc server host is big-endian, object file is not");
+    byteswap = 1;
   }
 #else
   if (elf32_header->e_ident[EI_DATA] != ELFDATA2LSB) {
-    rs_trace("sorry, not fixing debug info: "
-            "distcc server host is little-endian, object file is not");
-    return 0;
+    rs_trace("distcc server host is little-endian, object file is not");
+    byteswap = 1;
   }
 #endif
 
@@ -130,45 +162,45 @@
     const Elf32_Ehdr *elf_header = elf32_header;
     const Elf32_Shdr *sections =
         /* The double cast below avoids warnings with -Wcast-align. */
-        (const Elf32_Shdr *) (const void *) (elf_base + elf_header->e_shoff);
-    const Elf32_Shdr *string_section = sections + elf_header->e_shstrndx;
+        (const Elf32_Shdr *) (const void *) (elf_base + GET_ELF32_OFFSET(elf_header->e_shoff, byteswap));
+    const Elf32_Shdr *string_section = sections + GET_ELF32_HALF(elf_header->e_shstrndx, byteswap);
     const Elf32_Shdr *desired_section = NULL;
 
     if (elf_size < (off_t) sizeof(*elf_header)) {
       rs_trace("object file is too small for ELF header; maybe got truncated?");
       return 0;
     }
-    if (elf_header->e_shoff <= 0 ||
-        elf_header->e_shoff > elf_size - sizeof(Elf32_Shdr)) {
+    if (GET_ELF32_OFFSET(elf_header->e_shoff, byteswap) <= 0 ||
+        GET_ELF32_OFFSET(elf_header->e_shoff, byteswap) > elf_size - sizeof(Elf32_Shdr)) {
       rs_trace("invalid e_shoff value in ELF header");
       return 0;
     }
-    if (elf_header->e_shstrndx == SHN_UNDEF) {
+    if (GET_ELF32_HALF(elf_header->e_shstrndx, byteswap) == SHN_UNDEF) {
       rs_trace("object file has no section name string table"
                " (e_shstrndx == SHN_UNDEF)");
       return 0;
     }
     /* Special case for more sections than will fit in e_shstrndx. */
-    if (elf_header->e_shstrndx == SHN_XINDEX) {
-      string_section = sections + sections[0].sh_link;
+    if (GET_ELF32_HALF(elf_header->e_shstrndx, byteswap) == SHN_XINDEX) {
+      string_section = sections + GET_ELF32_WORD(sections[0].sh_link, byteswap);
     }
-    num_sections = elf_header->e_shnum;
+    num_sections = GET_ELF32_HALF(elf_header->e_shnum, byteswap);
     /* Special case for more sections than will fit in e_shnum. */
     if (num_sections == 0) {
-      num_sections = sections[0].sh_size;
+      num_sections = GET_ELF32_WORD(sections[0].sh_size, byteswap);
     }
     for (i = 0; i < num_sections; ++i) {
       const char *section_name = (char *)(elf_base +
-                                          string_section->sh_offset +
-                                          sections[i].sh_name);
+                                          GET_ELF32_OFFSET(string_section->sh_offset, byteswap) +
+                                          GET_ELF32_WORD(sections[i].sh_name, byteswap));
       if (!strcmp(section_name, desired_section_name)) {
         desired_section = &sections[i];
         break;
       }
     }
-    if (desired_section != NULL && desired_section->sh_size > 0) {
-      int desired_section_size = desired_section->sh_size;
-      *section_start = elf_base + desired_section->sh_offset;
+    if (desired_section != NULL && GET_ELF32_WORD(desired_section->sh_size, byteswap) > 0) {
+      int desired_section_size = GET_ELF32_WORD(desired_section->sh_size, byteswap);
+      *section_start = elf_base + GET_ELF32_OFFSET(desired_section->sh_offset, byteswap);
       *section_size = desired_section_size;
       return 1;
     } else {
@@ -178,45 +210,45 @@
     /* The double cast below avoids warnings with -Wcast-align. */
     const Elf64_Ehdr *elf_header = (const Elf64_Ehdr *) (const void *) elf_base;
     const Elf64_Shdr *sections =
-        (const Elf64_Shdr *) (const void *) (elf_base + elf_header->e_shoff);
-    const Elf64_Shdr *string_section = sections + elf_header->e_shstrndx;
+        (const Elf64_Shdr *) (const void *) (elf_base + GET_ELF64_OFFSET(elf_header->e_shoff, byteswap));
+    const Elf64_Shdr *string_section = sections + GET_ELF64_HALF(elf_header->e_shstrndx, byteswap);
     const Elf64_Shdr *desired_section = NULL;
 
     if (elf_size < (off_t) sizeof(*elf_header)) {
       rs_trace("object file is too small for ELF header; maybe got truncated?");
       return 0;
     }
-    if (elf_header->e_shoff <= 0 ||
-        elf_header->e_shoff > (size_t) elf_size - sizeof(Elf64_Shdr)) {
+    if (GET_ELF64_OFFSET(elf_header->e_shoff, byteswap) <= 0 ||
+        GET_ELF64_OFFSET(elf_header->e_shoff, byteswap) > (size_t) elf_size - sizeof(Elf64_Shdr)) {
       rs_trace("invalid e_shoff value in ELF header");
       return 0;
     }
-    if (elf_header->e_shstrndx == SHN_UNDEF) {
+    if (GET_ELF64_HALF(elf_header->e_shstrndx, byteswap) == SHN_UNDEF) {
       rs_trace("object file has no section name string table"
                " (e_shstrndx == SHN_UNDEF)");
       return 0;
     }
     /* Special case for more sections than will fit in e_shstrndx. */
-    if (elf_header->e_shstrndx == SHN_XINDEX) {
-      string_section = sections + sections[0].sh_link;
+    if (GET_ELF64_HALF(elf_header->e_shstrndx, byteswap) == SHN_XINDEX) {
+      string_section = sections + GET_ELF64_WORD(sections[0].sh_link, byteswap);
     }
-    num_sections = elf_header->e_shnum;
+    num_sections = GET_ELF64_HALF(elf_header->e_shnum, byteswap);
     if (num_sections == 0) {
       /* Special case for more sections than will fit in e_shnum. */
-      num_sections = sections[0].sh_size;
+      num_sections = GET_ELF64_XWORD(sections[0].sh_size, byteswap);
     }
     for (i = 0; i < num_sections; ++i) {
       const char *section_name = (char*)(elf_base +
-                                         string_section->sh_offset +
-                                         sections[i].sh_name);
+                                         GET_ELF64_OFFSET(string_section->sh_offset, byteswap) +
+                                         GET_ELF64_WORD(sections[i].sh_name, byteswap));
       if (!strcmp(section_name, desired_section_name)) {
         desired_section = &sections[i];
         break;
       }
     }
-    if (desired_section != NULL && desired_section->sh_size > 0) {
-      int desired_section_size = desired_section->sh_size;
-      *section_start = elf_base + desired_section->sh_offset;
+    if (desired_section != NULL && GET_ELF64_XWORD(desired_section->sh_size, byteswap) > 0) {
+      int desired_section_size = GET_ELF64_XWORD(desired_section->sh_size, byteswap);
+      *section_start = elf_base + GET_ELF64_OFFSET(desired_section->sh_offset, byteswap);
       *section_size = desired_section_size;
       return 1;
     } else {
