static int dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym) { sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab; shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB; shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB; uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB; size_t size; uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr; if (sym->sym_data_pri == NULL || sym->sym_symn == 0 || sym->sym_strs == NULL) return (0); size = sym->sym_hdr_pri.sh_size; if (gc_pwrite64(pgc->pgc_fd, sym->sym_data_pri->d_buf, size, *pgc->pgc_doff) != 0) return (-1); if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size, index + 1, sym->sym_hdr_pri.sh_info, sym->sym_hdr_pri.sh_addralign, sym->sym_hdr_pri.sh_entsize) != 0) return (-1); *pgc->pgc_doff += roundup(size, 8); size = sym->sym_strhdr.sh_size; if (gc_pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != 0) return (-1); if (write_shdr(pgc, strname, SHT_STRTAB, SHF_STRINGS, addr, *pgc->pgc_doff, size, 0, 0, 1, 0) != 0) return (-1); *pgc->pgc_doff += roundup(size, 8); return (0); }
int write_elf(struct _asm_context *asm_context, FILE *out) { unsigned char e_ident[16] = { 0x7f, 'E','L','F', 1, 1, 1, 0xff, 0, 0, 0, 0, 0, 0, 0, 0 }; struct _sections_offset sections_offset; struct _sections_size sections_size; struct _shdr shdr; struct _symtab symtab; int i; int e_flags; int e_shnum; int e_shstrndx=0; int text_addr[ELF_TEXT_MAX]; int data_addr[ELF_TEXT_MAX]; int text_count=0; int data_count=0; memset(§ions_offset, 0, sizeof(sections_offset)); memset(§ions_size, 0, sizeof(sections_size)); // Fill in blank to minimize text and data sections i=0; while (i<=asm_context->high_address) { if (asm_context->debug_line[i]==-2) { // Fill gaps in data sections while(asm_context->debug_line[i]==-2) { //printf("Found data %02x\n", i); while(i<=asm_context->high_address && asm_context->debug_line[i]==-2) { i+=2; } //printf("End data %02x\n", i); if (i==asm_context->high_address) break; int marker=i; while(i<=asm_context->high_address && asm_context->debug_line[i]==-1) { i+=2; } if (i==asm_context->high_address) break; if (i<=asm_context->high_address && asm_context->debug_line[i]==-2) { while(marker!=i) { asm_context->debug_line[marker++]=-2; } } if (i==asm_context->high_address) break; } } else if (asm_context->debug_line[i]>=0) { // Fill gaps in code sections while(i<=asm_context->high_address && asm_context->debug_line[i]>=0) { //printf("Found code %02x %d %d\n", i, asm_context->debug_line[i], asm_context->bin[i]); while(i<=asm_context->high_address && (asm_context->debug_line[i]>=0 || asm_context->debug_line[i]==-3)) { i+=2; } if (i==asm_context->high_address) break; //printf("End code %02x %d\n", i, asm_context->debug_line[i]); int marker=i; while(i<=asm_context->high_address && asm_context->debug_line[i]==-1) { i+=2; } if (i==asm_context->high_address) break; if (asm_context->debug_line[i]>=0) { while(marker!=i) { asm_context->debug_line[marker++]=-3; } } if (i==asm_context->high_address) break; } } i+=2; } // For now we will only have .text, .shstrtab, .symtab, strtab // I can't see a use for .data and .bss unless the bootloaders know elf? // I'm also not supporting relocations. I can do it later if requested. // Write string table char string_table[1024] = { "\0" //".text\0" //".rela.text\0" //".data\0" //".bss\0" ".shstrtab\0" ".symtab\0" ".strtab\0" ".comment\0" //".debug_line\0" //".rela.debug_line\0" //".debug_info\0" //".rela.debug_info\0" //".debug_abbrev\0" //".debug_aranges\0" //".rela.debug_aranges\0" }; e_flags=11; // mspgcc4/build/insight-6.8-1/include/elf/msp430.h e_shnum=4; //if (asm_context->debug_file==1) { e_shnum+=4; } e_shnum++; // Null section to start... // Write Ehdr; i=fwrite(e_ident, 1, 16, out); write_int16_l(out, 0); // e_type 0=not relocatable 1=msp_32 write_int16_l(out, 0x69); // e_machine EM_MSP430=0x69 write_int32_l(out, 1); // e_version write_int32_l(out, 0); // e_entry (this could be 16 bit at 0xfffe) write_int32_l(out, 0); // e_phoff (program header offset) write_int32_l(out, 0); // e_shoff (section header offset) write_int32_l(out, e_flags); // e_flags (should be set to CPU model) write_int16_l(out, 0x34); // e_ehsize (size of this struct) write_int16_l(out, 0); // e_phentsize (program header size) write_int16_l(out, 0); // e_phnum (number of program headers) write_int16_l(out, 40); // e_shentsize (section header size) write_int16_l(out, e_shnum); // e_shnum (number of section headers) write_int16_l(out, 2); // e_shstrndx (section header string table index) // .text and .data sections i=0; while (i<=asm_context->high_address) { char name[32]; if (asm_context->debug_line[i]==-2) { if (data_count>=ELF_TEXT_MAX) { printf("Too many elf .data sections (count=%d). Internal error.\n", data_count); exit(1); } if (data_count==0) { strcpy(name, ".data"); } else { sprintf(name, ".data%d", data_count); } data_addr[data_count]=i; string_table_append(string_table, name); sections_offset.data[data_count]=ftell(out); while(asm_context->debug_line[i]==-2) { putc(asm_context->bin[i++], out); putc(asm_context->bin[i++], out); } //i=fwrite(asm_context->bin+asm_context->low_address, 1, asm_context->high_address-asm_context->low_address+1, out); sections_size.data[data_count]=ftell(out)-sections_offset.data[data_count]; data_count++; e_shnum++; } else if (asm_context->debug_line[i]!=-1) { if (text_count>=ELF_TEXT_MAX) { printf("Too many elf .text sections(%d). Internal error.\n", text_count); exit(1); } if (text_count==0) { strcpy(name, ".text"); } else { sprintf(name, ".text%d", text_count); } text_addr[text_count]=i; printf("and i=%d text_count=%d\n", i, text_count); string_table_append(string_table, name); sections_offset.text[text_count]=ftell(out); while(asm_context->debug_line[i]>=0 || asm_context->debug_line[i]==-3) { putc(asm_context->bin[i++], out); putc(asm_context->bin[i++], out); } //i=fwrite(asm_context->bin+asm_context->low_address, 1, asm_context->high_address-asm_context->low_address+1, out); sections_size.text[text_count]=ftell(out)-sections_offset.text[text_count]; text_count++; e_shnum++; } i++; } e_shstrndx=data_count+text_count+1; // .shstrtab section sections_offset.shstrtab=ftell(out); i=fwrite(string_table, 1, get_string_table_len(string_table), out); putc(0x00, out); // null sections_size.shstrtab=ftell(out)-sections_offset.shstrtab; { struct _address_heap *address_heap=&asm_context->address_heap; int symbol_count=0; int sym_offset=0; int ptr,n; // Count symbols ptr=0; while(ptr<address_heap->ptr) { int token_len=strlen((char *)address_heap->buffer+ptr)+1; //fprintf(out, "%s", address_heap->buffer+ptr); ptr=ptr+token_len+sizeof(int); symbol_count++; } int symbol_address[symbol_count]; // .strtab section elf_addr_align(out); sections_offset.strtab=ftell(out); putc(0x00, out); // none fprintf(out, "%s%c", asm_context->filename, 0); sym_offset=strlen(asm_context->filename)+2; ptr=0; n=0; while(ptr<address_heap->ptr) { symbol_address[n++]=sym_offset; int token_len=strlen((char *)address_heap->buffer+ptr)+1; fprintf(out, "%s%c", address_heap->buffer+ptr, 0); ptr=ptr+token_len+sizeof(int); sym_offset+=token_len; } putc(0x00, out); // null sections_size.strtab=ftell(out)-sections_offset.strtab; // .symtab section elf_addr_align(out); sections_offset.symtab=ftell(out); // symtab text memset(&symtab, 0, sizeof(symtab)); symtab.st_info=3; symtab.st_shndx=1; write_symtab(out, &symtab); // symtab filename memset(&symtab, 0, sizeof(symtab)); symtab.st_name=1; symtab.st_info=4; write_symtab(out, &symtab); // symbols from lookup tables ptr=0; n=0; while(ptr<address_heap->ptr) { int token_len=strlen((char *)address_heap->buffer+ptr)+1; memset(&symtab, 0, sizeof(symtab)); unsigned char *data=address_heap->buffer+ptr+token_len; symtab.st_name=symbol_address[n++]; symtab.st_value=data[0]|(data[1]<<8)|(data[2]<<16)|(data[3]<<24); symtab.st_shndx=1; write_symtab(out, &symtab); ptr=ptr+token_len+sizeof(int); } sections_size.symtab=ftell(out)-sections_offset.symtab; } // .comment section sections_offset.comment=ftell(out); fprintf(out, "Created with naken430asm. http://www.mikekohn.net/"); sections_size.comment=ftell(out)-sections_offset.comment; if (asm_context->debug_file==1) { // insert debug sections } // A little ex-lax to dump the SHT's long marker=ftell(out); fseek(out, 32, SEEK_SET); write_int32_l(out, marker); // e_shoff (section header offset) fseek(out, 0x30, SEEK_SET); write_int16_l(out, e_shnum); // e_shnum (section count) write_int16_l(out, e_shstrndx); // e_shstrndx (string_table index) fseek(out, marker, SEEK_SET); memset(&shdr, 0, sizeof(shdr)); write_shdr(out, &shdr); // SHT .text for (i=0; i<text_count; i++) { char name[32]; if (i==0) { strcpy(name, ".text"); } else { sprintf(name, ".text%d", i); } shdr.sh_name=find_section(string_table, name, sizeof(string_table)); printf("name=%s (%d) %s\n", name, shdr.sh_name, string_table+ shdr.sh_name); shdr.sh_type=1; shdr.sh_flags=6; printf("text_addr=%d\n", text_addr[i]); shdr.sh_addr=text_addr[i]; //asm_context->low_address; shdr.sh_offset=sections_offset.text[i]; shdr.sh_size=sections_size.text[i]; shdr.sh_addralign=1; write_shdr(out, &shdr); } // SHT .data for (i=0; i<data_count; i++) { char name[32]; if (i==0) { strcpy(name, ".data"); } else { sprintf(name, ".data%d", i); } shdr.sh_name=find_section(string_table, name, sizeof(string_table)); shdr.sh_type=1; shdr.sh_flags=3; shdr.sh_addr=data_addr[i]; //asm_context->low_address; shdr.sh_offset=sections_offset.data[i]; shdr.sh_size=sections_size.data[i]; shdr.sh_addralign=1; write_shdr(out, &shdr); } // SHT .shstrtab memset(&shdr, 0, sizeof(shdr)); shdr.sh_name=find_section(string_table, ".shstrtab", sizeof(string_table)); shdr.sh_type=3; shdr.sh_offset=sections_offset.shstrtab; shdr.sh_size=sections_size.shstrtab; shdr.sh_addralign=1; write_shdr(out, &shdr); // SHT .symtab memset(&shdr, 0, sizeof(shdr)); shdr.sh_name=find_section(string_table, ".symtab", sizeof(string_table)); shdr.sh_type=2; shdr.sh_offset=sections_offset.symtab; shdr.sh_size=sections_size.symtab; shdr.sh_addralign=4; shdr.sh_entsize=16; write_shdr(out, &shdr); // SHT .strtab memset(&shdr, 0, sizeof(shdr)); shdr.sh_name=find_section(string_table, ".strtab", sizeof(string_table)); shdr.sh_type=3; shdr.sh_offset=sections_offset.strtab; shdr.sh_size=sections_size.strtab; shdr.sh_addralign=1; write_shdr(out, &shdr); // SHT .comment memset(&shdr, 0, sizeof(shdr)); shdr.sh_name=find_section(string_table, ".comment", sizeof(string_table)); shdr.sh_type=1; shdr.sh_offset=sections_offset.comment; shdr.sh_size=sections_size.comment; shdr.sh_addralign=1; write_shdr(out, &shdr); if (asm_context->debug_file==1) { // insert debug SHT's } return 0; }
int rewrite_code_section(elf_data_t *elf, inject_data_t *inject, char **err) { Elf_Scn *scn; GElf_Shdr shdr; char *s; size_t shstrndx; if(elf_getshdrstrndx(elf->e, &shstrndx) < 0) { (*err) = "failed to get string table section index"; return -1; } printf("shstrndx : %d\n",shstrndx); scn = NULL; while((scn = elf_nextscn(elf->e, scn))) { if(!gelf_getshdr(scn, &shdr)) { (*err) = "failed to get section header"; return -1; } s = elf_strptr(elf->e, shstrndx, shdr.sh_name); if(!s) { (*err) = "failed to get section name"; return -1; } printf("section : %s\n",s); if(!strcmp(s, ABITAG_NAME)) { shdr.sh_name = shdr.sh_name; /* offset into string table */ shdr.sh_type = SHT_PROGBITS; /* type */ shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; /* flags */ shdr.sh_addr = inject->secaddr; /* address to load section at */ shdr.sh_offset = inject->off; /* file offset to start of section */ shdr.sh_size = inject->len; /* size in bytes */ shdr.sh_link = 0; /* not used for code section */ shdr.sh_info = 0; /* not used for code section */ shdr.sh_addralign = 16; /* memory alignment */ shdr.sh_entsize = 0; /* not used for code section */ verbose("rewriting section header %lu:", elf_ndxscn(scn)); verbose(" sh_name = %u", shdr.sh_name); verbose(" sh_type = SHT_PROGBITS"); verbose(" sh_flags = SHF_ALLOC | SHF_EXECINSTR"); verbose(" sh_addr = 0x%x", shdr.sh_addr); verbose(" sh_offset = %lu", shdr.sh_offset); verbose(" sh_size = %lu", shdr.sh_size); verbose(" sh_link = 0"); verbose(" sh_info = 0"); verbose(" sh_addralign = 0x%x", shdr.sh_addralign); verbose(" sh_entsize = 0"); inject->sidx = elf_ndxscn(scn); inject->scn = scn; memcpy(&inject->shdr, &shdr, sizeof(shdr)); verbose("writing section header to file"); if(write_shdr(elf, scn, &shdr, elf_ndxscn(scn), err) < 0) { return -1; } if(reorder_shdrs(elf, inject, err) < 0) { return -1; } break; } } if(!scn) { (*err) = "cannot find section to rewrite"; return -1; } return 0; }
int reorder_shdrs(elf_data_t *elf, inject_data_t *inject, char **err) { int direction, skip; size_t i; Elf_Scn *scn; GElf_Shdr shdr; direction = 0; scn = elf_getscn(elf->e, inject->sidx - 1); if(scn && !gelf_getshdr(scn, &shdr)) { (*err) = "failed to get section header"; return -1; } if(scn && shdr.sh_addr > inject->shdr.sh_addr) { /* Injected section header must be moved left */ direction = -1; } scn = elf_getscn(elf->e, inject->sidx + 1); if(scn && !gelf_getshdr(scn, &shdr)) { (*err) = "failed to get section header"; return -1; } if(scn && shdr.sh_addr < inject->shdr.sh_addr) { /* Injected section header must be moved right */ direction = 1; } if(direction == 0) { /* Section headers are already in order */ return 0; } i = inject->sidx; /* Order section headers by increasing address */ skip = 0; for(scn = elf_getscn(elf->e, inject->sidx + direction); scn != NULL; scn = elf_getscn(elf->e, inject->sidx + direction + skip)) { if(!gelf_getshdr(scn, &shdr)) { (*err) = "failed to get section header"; return -1; } if((direction < 0 && shdr.sh_addr <= inject->shdr.sh_addr) || (direction > 0 && shdr.sh_addr >= inject->shdr.sh_addr)) { /* The order is okay from this point on */ break; } /* Only reorder code section headers */ if(shdr.sh_type != SHT_PROGBITS) { skip += direction; continue; } /* Swap the injected shdr with its neighbor progbits header */ if(write_shdr(elf, scn, &inject->shdr, elf_ndxscn(scn), err) < 0) { return -1; } if(write_shdr(elf, inject->scn, &shdr, inject->sidx, err) < 0) { return -1; } inject->sidx += direction + skip; inject->scn = elf_getscn(elf->e, inject->sidx); skip = 0; } verbose("reordered sections %lu - %lu", i, inject->sidx); return 0; }
static int dump_sections(pgcore_t *pgc) { struct ps_prochandle *P = pgc->P; file_info_t *fptr; uint_t cnt; uint_t index = 1; if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB))) return (0); fptr = list_next(&P->file_head); for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) { int hit_symtab = 0; Pbuild_file_symtab(P, fptr); if ((pgc->pgc_content & CC_CONTENT_CTF) && Pbuild_file_ctf(P, fptr) != NULL) { sym_tbl_t *sym; uint_t dynsym; uint_t symindex = 0; /* * Write the symtab out first so we can correctly * set the sh_link field in the CTF section header. * symindex will be 0 if there is no corresponding * symbol table section. */ if (fptr->file_ctf_dyn) { sym = &fptr->file_dynsym; dynsym = 1; } else { sym = &fptr->file_symtab; dynsym = 0; hit_symtab = 1; } if (sym->sym_data_pri != NULL && sym->sym_symn != 0 && sym->sym_strs != NULL) { symindex = index; if (dump_symtab(pgc, fptr, index, dynsym) != 0) return (-1); index += 2; } /* * Write the CTF data that we've read out of the * file itself into the core file. */ if (gc_pwrite64(pgc->pgc_fd, fptr->file_ctf_buf, fptr->file_ctf_size, *pgc->pgc_doff) != 0) return (-1); if (write_shdr(pgc, STR_CTF, SHT_PROGBITS, 0, fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff, fptr->file_ctf_size, symindex, 0, 4, 0) != 0) return (-1); index++; *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8); } if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && fptr->file_symtab.sym_data_pri != NULL && fptr->file_symtab.sym_symn != 0 && fptr->file_symtab.sym_strs != NULL) { if (dump_symtab(pgc, fptr, index, 0) != 0) return (-1); index += 2; } } return (0); }
/* * Don't explicity stop the process; that's up to the consumer. */ int Pfgcore(struct ps_prochandle *P, int fd, core_content_t content) { char plat[SYS_NMLN]; char zonename[ZONENAME_MAX]; int platlen = -1; pgcore_t pgc; off64_t poff, soff, doff, boff; struct utsname uts; uint_t nphdrs, nshdrs; if (ftruncate64(fd, 0) != 0) return (-1); if (content == CC_CONTENT_INVALID) { errno = EINVAL; return (-1); } /* * Cache the mappings and other useful data. */ (void) Prd_agent(P); (void) Ppsinfo(P); pgc.P = P; pgc.pgc_fd = fd; pgc.pgc_poff = &poff; pgc.pgc_soff = &soff; pgc.pgc_doff = &doff; pgc.pgc_content = content; pgc.pgc_chunksz = PAGESIZE; if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL) return (-1); shstrtab_init(&pgc.pgc_shstrtab); /* * There are two PT_NOTE program headers for ancillary data, and * one for each mapping. */ nphdrs = 2 + P->map_count; nshdrs = count_sections(&pgc); (void) Pplatform(P, plat, sizeof (plat)); platlen = strlen(plat) + 1; Preadauxvec(P); (void) Puname(P, &uts); if (Pzonename(P, zonename, sizeof (zonename)) == NULL) zonename[0] = '\0'; /* * The core file contents may required zero section headers, but if we * overflow the 16 bits allotted to the program header count in the ELF * header, we'll need that program header at index zero. */ if (nshdrs == 0 && nphdrs >= PN_XNUM) nshdrs = 1; /* * Set up the ELF header. */ if (P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Ehdr ehdr; bzero(&ehdr, sizeof (ehdr)); ehdr.e_ident[EI_MAG0] = ELFMAG0; ehdr.e_ident[EI_MAG1] = ELFMAG1; ehdr.e_ident[EI_MAG2] = ELFMAG2; ehdr.e_ident[EI_MAG3] = ELFMAG3; ehdr.e_type = ET_CORE; ehdr.e_ident[EI_CLASS] = ELFCLASS32; #if defined(__sparc) ehdr.e_machine = EM_SPARC; ehdr.e_ident[EI_DATA] = ELFDATA2MSB; #elif defined(__i386) || defined(__amd64) ehdr.e_machine = EM_386; ehdr.e_ident[EI_DATA] = ELFDATA2LSB; #else #error "unknown machine type" #endif ehdr.e_ident[EI_VERSION] = EV_CURRENT; ehdr.e_version = EV_CURRENT; ehdr.e_ehsize = sizeof (ehdr); if (nphdrs >= PN_XNUM) ehdr.e_phnum = PN_XNUM; else ehdr.e_phnum = (unsigned short)nphdrs; ehdr.e_phentsize = sizeof (Elf32_Phdr); ehdr.e_phoff = ehdr.e_ehsize; if (nshdrs > 0) { if (nshdrs >= SHN_LORESERVE) ehdr.e_shnum = 0; else ehdr.e_shnum = (unsigned short)nshdrs; if (nshdrs - 1 >= SHN_LORESERVE) ehdr.e_shstrndx = SHN_XINDEX; else ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); ehdr.e_shentsize = sizeof (Elf32_Shdr); ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; } if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0) goto err; poff = ehdr.e_phoff; soff = ehdr.e_shoff; doff = boff = ehdr.e_ehsize + ehdr.e_phentsize * nphdrs + ehdr.e_shentsize * nshdrs; #ifdef _LP64 } else { Elf64_Ehdr ehdr; bzero(&ehdr, sizeof (ehdr)); ehdr.e_ident[EI_MAG0] = ELFMAG0; ehdr.e_ident[EI_MAG1] = ELFMAG1; ehdr.e_ident[EI_MAG2] = ELFMAG2; ehdr.e_ident[EI_MAG3] = ELFMAG3; ehdr.e_type = ET_CORE; ehdr.e_ident[EI_CLASS] = ELFCLASS64; #if defined(__sparc) ehdr.e_machine = EM_SPARCV9; ehdr.e_ident[EI_DATA] = ELFDATA2MSB; #elif defined(__i386) || defined(__amd64) ehdr.e_machine = EM_AMD64; ehdr.e_ident[EI_DATA] = ELFDATA2LSB; #else #error "unknown machine type" #endif ehdr.e_ident[EI_VERSION] = EV_CURRENT; ehdr.e_version = EV_CURRENT; ehdr.e_ehsize = sizeof (ehdr); if (nphdrs >= PN_XNUM) ehdr.e_phnum = PN_XNUM; else ehdr.e_phnum = (unsigned short)nphdrs; ehdr.e_phentsize = sizeof (Elf64_Phdr); ehdr.e_phoff = ehdr.e_ehsize; if (nshdrs > 0) { if (nshdrs >= SHN_LORESERVE) ehdr.e_shnum = 0; else ehdr.e_shnum = (unsigned short)nshdrs; if (nshdrs - 1 >= SHN_LORESERVE) ehdr.e_shstrndx = SHN_XINDEX; else ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); ehdr.e_shentsize = sizeof (Elf64_Shdr); ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; } if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0) goto err; poff = ehdr.e_phoff; soff = ehdr.e_shoff; doff = boff = ehdr.e_ehsize + ehdr.e_phentsize * nphdrs + ehdr.e_shentsize * nshdrs; #endif /* _LP64 */ } /* * Write the zero indexed section if it exists. */ if (nshdrs > 0 && write_shdr(&pgc, STR_NONE, 0, 0, 0, 0, nshdrs >= SHN_LORESERVE ? nshdrs : 0, nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0, nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0) goto err; /* * Construct the old-style note header and section. */ if (P->status.pr_dmodel == PR_MODEL_NATIVE) { prpsinfo_t prpsinfo; mkprpsinfo(P, &prpsinfo); if (write_note(fd, NT_PRPSINFO, &prpsinfo, sizeof (prpsinfo_t), &doff) != 0) { goto err; } if (write_note(fd, NT_AUXV, P->auxv, P->nauxv * sizeof (P->auxv[0]), &doff) != 0) { goto err; } #ifdef _LP64 } else { prpsinfo32_t pi32; auxv32_t *av32; size_t size = sizeof (auxv32_t) * P->nauxv; int i; mkprpsinfo32(P, &pi32); if (write_note(fd, NT_PRPSINFO, &pi32, sizeof (prpsinfo32_t), &doff) != 0) { goto err; } if ((av32 = malloc(size)) == NULL) goto err; for (i = 0; i < P->nauxv; i++) { auxv_n_to_32(&P->auxv[i], &av32[i]); } if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) { free(av32); goto err; } free(av32); #endif /* _LP64 */ } if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0) goto err; if (Plwp_iter_all(P, old_per_lwp, &pgc) != 0) goto err; if (P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Phdr phdr; bzero(&phdr, sizeof (phdr)); phdr.p_type = PT_NOTE; phdr.p_flags = PF_R; phdr.p_offset = (Elf32_Off)boff; phdr.p_filesz = doff - boff; boff = doff; if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) goto err; poff += sizeof (phdr); #ifdef _LP64 } else { Elf64_Phdr phdr; bzero(&phdr, sizeof (phdr)); phdr.p_type = PT_NOTE; phdr.p_flags = PF_R; phdr.p_offset = boff; phdr.p_filesz = doff - boff; boff = doff; if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) goto err; poff += sizeof (phdr); #endif /* _LP64 */ } /* * Construct the new-style note header and section. */ if (P->status.pr_dmodel == PR_MODEL_NATIVE) { if (write_note(fd, NT_PSINFO, &P->psinfo, sizeof (psinfo_t), &doff) != 0) { goto err; } if (write_note(fd, NT_PSTATUS, &P->status, sizeof (pstatus_t), &doff) != 0) { goto err; } if (write_note(fd, NT_AUXV, P->auxv, P->nauxv * sizeof (P->auxv[0]), &doff) != 0) { goto err; } #ifdef _LP64 } else { psinfo32_t pi32; pstatus32_t ps32; auxv32_t *av32; size_t size = sizeof (auxv32_t) * P->nauxv; int i; psinfo_n_to_32(&P->psinfo, &pi32); if (write_note(fd, NT_PSINFO, &pi32, sizeof (psinfo32_t), &doff) != 0) { goto err; } pstatus_n_to_32(&P->status, &ps32); if (write_note(fd, NT_PSTATUS, &ps32, sizeof (pstatus32_t), &doff) != 0) { goto err; } if ((av32 = malloc(size)) == NULL) goto err; for (i = 0; i < P->nauxv; i++) { auxv_n_to_32(&P->auxv[i], &av32[i]); } if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) { free(av32); goto err; } free(av32); #endif /* _LP64 */ } if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0 || write_note(fd, NT_UTSNAME, &uts, sizeof (uts), &doff) != 0 || write_note(fd, NT_CONTENT, &content, sizeof (content), &doff) != 0) goto err; { prcred_t cred, *cp; size_t size = sizeof (prcred_t); if (Pcred(P, &cred, 0) != 0) goto err; if (cred.pr_ngroups > 0) size += sizeof (gid_t) * (cred.pr_ngroups - 1); if ((cp = malloc(size)) == NULL) goto err; if (Pcred(P, cp, cred.pr_ngroups) != 0 || write_note(fd, NT_PRCRED, cp, size, &doff) != 0) { free(cp); goto err; } free(cp); } { prpriv_t *ppriv = NULL; const priv_impl_info_t *pinfo; size_t pprivsz, pinfosz; if (Ppriv(P, &ppriv) == -1) goto err; pprivsz = PRIV_PRPRIV_SIZE(ppriv); if (write_note(fd, NT_PRPRIV, ppriv, pprivsz, &doff) != 0) { Ppriv_free(P, ppriv); goto err; } Ppriv_free(P, ppriv); if ((pinfo = getprivimplinfo()) == NULL) goto err; pinfosz = PRIV_IMPL_INFO_SIZE(pinfo); if (write_note(fd, NT_PRPRIVINFO, pinfo, pinfosz, &doff) != 0) goto err; } if (write_note(fd, NT_ZONENAME, zonename, strlen(zonename) + 1, &doff) != 0) goto err; { fditer_t iter; iter.fd_fd = fd; iter.fd_doff = &doff; if (Pfdinfo_iter(P, iter_fd, &iter) != 0) goto err; } { prsecflags_t *psf = NULL; if (Psecflags(P, &psf) != 0) goto err; if (write_note(fd, NT_SECFLAGS, psf, sizeof (prsecflags_t), &doff) != 0) { Psecflags_free(psf); goto err; } Psecflags_free(psf); } #if defined(__i386) || defined(__amd64) /* CSTYLED */ { struct ssd *ldtp; size_t size; int nldt; /* * Only dump out non-zero sized LDT notes. */ if ((nldt = Pldt(P, NULL, 0)) != 0) { size = sizeof (struct ssd) * nldt; if ((ldtp = malloc(size)) == NULL) goto err; if (Pldt(P, ldtp, nldt) == -1 || write_note(fd, NT_LDT, ldtp, size, &doff) != 0) { free(ldtp); goto err; } free(ldtp); } } #endif /* __i386 || __amd64 */ if (Plwp_iter_all(P, new_per_lwp, &pgc) != 0) goto err; if (P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Phdr phdr; bzero(&phdr, sizeof (phdr)); phdr.p_type = PT_NOTE; phdr.p_flags = PF_R; phdr.p_offset = (Elf32_Off)boff; phdr.p_filesz = doff - boff; boff = doff; if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) goto err; poff += sizeof (phdr); #ifdef _LP64 } else { Elf64_Phdr phdr; bzero(&phdr, sizeof (phdr)); phdr.p_type = PT_NOTE; phdr.p_flags = PF_R; phdr.p_offset = boff; phdr.p_filesz = doff - boff; boff = doff; if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) goto err; poff += sizeof (phdr); #endif /* _LP64 */ } /* * Construct the headers for each mapping and write out its data * if the content parameter indicates that it should be present * in the core file. */ if (Pmapping_iter(P, dump_map, &pgc) != 0) goto err; if (dump_sections(&pgc) != 0) goto err; if (write_shstrtab(P, &pgc) != 0) goto err; free(pgc.pgc_chunk); return (0); err: /* * Wipe out anything we may have written if there was an error. */ (void) ftruncate64(fd, 0); free(pgc.pgc_chunk); return (-1); }