$NetBSD: patch-az,v 1.1 1999/02/04 14:54:25 frueauf Exp $ --- src/unexelf.c.orig Mon Aug 10 04:33:12 1998 +++ src/unexelf.c Thu Feb 4 12:46:44 1999 @@ -501,9 +501,16 @@ # include # define HDRR struct ecoff_symhdr # define pHDRR HDRR * -# endif +# endif /* __alpha__*/ + +# ifdef __mips__ +# define SHT_MIPS_DEBUG DT_MIPS_FLAGS +# define HDRR struct Elf_Shdr +# endif /* __mips__ */ + #endif /* __NetBSD__ */ + #ifdef __OpenBSD__ # include #endif @@ -527,6 +534,14 @@ extern void fatal (char *, ...); #endif +#if defined ( __sony_news) && defined (_SYSTYPE_SYSV) +# define HAVE_MIPS_SBSS +#endif + +#if defined (__mips__) && (defined(__NetBSD__) || defined(__OpenBSD__)) +# define HAVE_MIPS_SBSS +#endif + #ifndef ELF_BSS_SECTION_NAME #define ELF_BSS_SECTION_NAME ".bss" #endif @@ -585,6 +600,47 @@ return x - rem + y; } +#if defined(__alpha__) || (defined ( __sony_news) && defined (_SYSTYPE_SYSV)) +/* We are using ECOFF symbols embedded in ELF. */ + +void +relocate_ecoff_symhdr(symhdr, diff) + HDRR *symhdr; + Elfw(Word) diff; +{ + symhdr->cbLineOffset += diff; + symhdr->cbDnOffset += diff; + symhdr->cbPdOffset += diff; + symhdr->cbSymOffset += diff; + symhdr->cbOptOffset += diff; + symhdr->cbAuxOffset += diff; + symhdr->cbSsOffset += diff; + symhdr->cbSsExtOffset += diff; + symhdr->cbFdOffset += diff; + symhdr->cbRfdOffset += diff; + symhdr->cbExtOffset += diff; +} +#endif /* __alpha__ or __sony_news and systype_sysv */ + +#ifdef notyet +void +relocate_elf_proghdr(p, diff) + HDRR *symhdr; + Elfw(Word) diff; +{ + phdr->sh_name += diff; + phdr->sh_type += diff; + phdr->sh_flags += diff; + phdr->sh_addr += diff; + phdr->sh_offset += diff; + phdr->sh_size += diff; + phdr->sh_link += diff; + phdr->sh_info += diff; + phdr->sh_addralign += diff; + phdr->sh_entsize += diff; +}; +#endif /* notyet */ + /* **************************************************************** * unexec * @@ -620,9 +676,10 @@ ElfW(Addr) new_data2_addr; int n, nn, old_bss_index, old_data_index, new_data2_index; -#if defined ( __sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS int old_sbss_index, old_mdebug_index; -#endif /* __sony_news && _SYSTYPE_SYSV */ + int bss_phdr_index; +#endif /* HAVE_MIPS_SBSS */ struct stat stat_buf; /* Open the old file & map it into the address space. */ @@ -672,7 +729,7 @@ if (old_bss_index == old_file_h->e_shnum) fatal ("Can't find .bss in %s.\n", old_name, 0); -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum; old_sbss_index++) { @@ -713,10 +770,10 @@ } if (old_mdebug_index == old_file_h->e_shnum) old_mdebug_index = 0; -#else /* not (__sony_news && _SYSTYPE_SYSV) */ +#else /* not HAVE_MIPS_SBSS */ old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; -#endif /* not (__sony_news && _SYSTYPE_SYSV) */ +#endif /* not HAVE_MIPS_SBSS */ #if defined (emacs) || !defined (DEBUG) new_bss_addr = (ElfW(Addr)) sbrk (0); #else @@ -724,9 +781,9 @@ #endif new_data2_addr = old_bss_addr; new_data2_size = new_bss_addr - old_bss_addr; -#if !defined (__sony_news) || !defined (_SYSTYPE_SYSV) +#ifndef HAVE_MIPS_SBSS new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; -#endif /* not (__sony_news && _SYSTYPE_SYSV) */ +#endif /* not HAVE_MIPS_SBSS */ #ifdef DEBUG fprintf (stderr, "old_bss_index %d\n", old_bss_index); @@ -811,14 +868,14 @@ if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) alignment = OLD_SECTION_H (old_bss_index).sh_addralign; -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > round_up (old_bss_addr, alignment)) fatal ("Program segment above .bss in %s\n", old_name, 0); -#else /* not (__sony_news && _SYSTYPE_SYSV) */ +#else /* not HAVE_MIPS_SBSS */ if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) fatal ("Program segment above .bss in %s\n", old_name, 0); -#endif /* not (__sony_news && _SYSTYPE_SYSV) */ +#endif /* not HAVE_MIPS_SBSS */ if (NEW_PROGRAM_H (n).p_type == PT_LOAD && (round_up ((NEW_PROGRAM_H (n)).p_vaddr @@ -830,11 +887,16 @@ if (n < 0) fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); +#ifdef HAVE_MIPS_SBSS + bss_phdr_index = n; +#endif + /* Make sure that the size includes any padding before the old .bss section. */ NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; + #if 0 /* Maybe allow section after data2 - does this ever happen? */ for (n = new_file_h->e_phnum - 1; n >= 0; n--) { @@ -867,15 +929,15 @@ { caddr_t src; int temp_index; -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS /* If it is (s)bss section, insert the new data2 section before it. */ /* new_data2_index is the index of either old_sbss or old_bss, that was chosen as a section for new_data2. */ temp_index = new_data2_index; -#else /* not (__sony_news && _SYSTYPE_SYSV) */ +#else /* not HAVE_MIPS_SBSS */ /* If it is bss section, insert the new data2 section before it. */ temp_index = old_bss_index; -#endif /* not (__sony_news && _SYSTYPE_SYSV) */ +#endif /* not HAVE_MIPS_SBSS */ if (n == temp_index) { /* Steal the data section header for this data2 section. */ @@ -901,11 +963,11 @@ old_file_h->e_shentsize); if (n == old_bss_index -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS /* The new bss and sbss section's size is zero, and its file offset and virtual address should be off by NEW_DATA2_SIZE. */ || n == old_sbss_index -#endif /* __sony_news and _SYSTYPE_SYSV */ +#endif /* HAVE_MIPS_SBSS */ ) { /* NN should be `old_bss_index + 1' at this point. */ @@ -916,6 +978,28 @@ this section will be placed in exactly the same place. */ NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; NEW_SECTION_H (nn).sh_size = 0; + +#ifdef HAVE_MIPS_SBSS + /* On ELF mips, the new data section replaces both .sbss and .bss + (we have, after all, written to them.). Adding new_data2_size + to the sh_addr and sh_offset of sbss puts sbss at the end of + the new data section. setting the size to zero makes it empty. + But then, adding the new_data2_size to the bss address puts + its start beyond the end of the original bss. If the sbss size + was bigger than a page, the bss ends up not covered by the + program header. This breaks strip. Since both sbss and bss + are zero-sized, just use the same address and file offset for + both, guaranteeing other tools will assign them to the same + program section (asssuming no sections are loaded at higher + offsets.) */ + if (n == old_bss_index) { + int new_sbss_bss_padding = NEW_SECTION_H(nn).sh_addr - + NEW_SECTION_H(nn - 1).sh_addr; + printf("sbss to bss offset =0x%x\n", new_sbss_bss_padding); + NEW_SECTION_H(nn).sh_addr =NEW_SECTION_H(nn - 1).sh_addr; + NEW_SECTION_H(nn).sh_offset =NEW_SECTION_H(nn - 1).sh_offset; + } +#endif /* HAVE_MIPS_SBSS */ } else { @@ -970,14 +1054,14 @@ || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name), ".sdata") #endif -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".sdata") || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".lit4") || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".lit8") -#endif /* __sony_news && _SYSTYPE_SYSV */ +#endif /* HAVE_MIPS_SBSS */ || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".data1")) src = (caddr_t) OLD_SECTION_H (n).sh_addr; @@ -993,22 +1077,11 @@ == 0) { pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); - - symhdr->cbLineOffset += new_data2_size; - symhdr->cbDnOffset += new_data2_size; - symhdr->cbPdOffset += new_data2_size; - symhdr->cbSymOffset += new_data2_size; - symhdr->cbOptOffset += new_data2_size; - symhdr->cbAuxOffset += new_data2_size; - symhdr->cbSsOffset += new_data2_size; - symhdr->cbSsExtOffset += new_data2_size; - symhdr->cbFdOffset += new_data2_size; - symhdr->cbRfdOffset += new_data2_size; - symhdr->cbExtOffset += new_data2_size; + relocate_ecoff_symhdr(symhdr, new_data2_size); } #endif /* __alpha__ */ -#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#ifdef HAVE_MIPS_SBSS if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) { int diff = NEW_SECTION_H(nn).sh_offset @@ -1017,20 +1090,17 @@ if (diff) { - phdr->cbLineOffset += diff; - phdr->cbDnOffset += diff; - phdr->cbPdOffset += diff; - phdr->cbSymOffset += diff; - phdr->cbOptOffset += diff; - phdr->cbAuxOffset += diff; - phdr->cbSsOffset += diff; - phdr->cbSsExtOffset += diff; - phdr->cbFdOffset += diff; - phdr->cbRfdOffset += diff; - phdr->cbExtOffset += diff; +#if defined ( __sony_news) && defined (_SYSTYPE_SYSV) + relocate_ecoff_symhdr(phdr, diff); +#else + /* xxxBSD with GNU binutils has .mdebug, but not ecoff(???) */ +#ifdef DEBUG + printf("Dont know how to relocate mdebug syms by %0x\n", diff); +#endif +#endif } } -#endif /* __sony_news && _SYSTYPE_SYSV */ +#endif /* HAVE_MIPS_SBSS */ /* If it is the symbol table, its st_shndx field needs to be patched. */ if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)