Changeset View
Standalone View
sys/kern/imgact_elf.c
Show First 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | |||||
SYSCTL_BOOL(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, allow_wx, | SYSCTL_BOOL(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, allow_wx, | ||||
CTLFLAG_RWTUN, &__elfN(allow_wx), 0, | CTLFLAG_RWTUN, &__elfN(allow_wx), 0, | ||||
"Allow pages to be mapped simultaneously writable and executable"); | "Allow pages to be mapped simultaneously writable and executable"); | ||||
static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; | static Elf_Brandinfo *elf_brand_list[MAX_BRANDS]; | ||||
#define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a)) | #define aligned(a, t) (rounddown2((u_long)(a), sizeof(t)) == (u_long)(a)) | ||||
static const char FREEBSD_ABI_VENDOR[] = "FreeBSD"; | |||||
Elf_Brandnote __elfN(freebsd_brandnote) = { | Elf_Brandnote __elfN(freebsd_brandnote) = { | ||||
.hdr.n_namesz = sizeof(FREEBSD_ABI_VENDOR), | .hdr.n_namesz = sizeof(FREEBSD_ABI_VENDOR), | ||||
.hdr.n_descsz = sizeof(int32_t), | .hdr.n_descsz = sizeof(int32_t), | ||||
.hdr.n_type = NT_FREEBSD_ABI_TAG, | .hdr.n_type = NT_FREEBSD_ABI_TAG, | ||||
.vendor = FREEBSD_ABI_VENDOR, | .vendor = FREEBSD_ABI_VENDOR, | ||||
.flags = BN_TRANSLATE_OSREL, | .flags = BN_TRANSLATE_OSREL, | ||||
.trans_osrel = __elfN(freebsd_trans_osrel) | .trans_osrel = __elfN(freebsd_trans_osrel) | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 1,219 Lines • ▼ Show 20 Lines | |||||
typedef void (*segment_callback)(vm_map_entry_t, void *); | typedef void (*segment_callback)(vm_map_entry_t, void *); | ||||
/* Closure for cb_put_phdr(). */ | /* Closure for cb_put_phdr(). */ | ||||
struct phdr_closure { | struct phdr_closure { | ||||
Elf_Phdr *phdr; /* Program header to fill in */ | Elf_Phdr *phdr; /* Program header to fill in */ | ||||
Elf_Off offset; /* Offset of segment in core file */ | Elf_Off offset; /* Offset of segment in core file */ | ||||
}; | }; | ||||
typedef void (*outfunc_t)(void *, struct sbuf *, size_t *); | |||||
struct note_info { | struct note_info { | ||||
int type; /* Note type. */ | int type; /* Note type. */ | ||||
outfunc_t outfunc; /* Output function. */ | outfunc_t outfunc; /* Output function. */ | ||||
void *outarg; /* Argument for the output function. */ | void *outarg; /* Argument for the output function. */ | ||||
size_t outsize; /* Output size. */ | size_t outsize; /* Output size. */ | ||||
TAILQ_ENTRY(note_info) link; /* Link to the next note info. */ | TAILQ_ENTRY(note_info) link; /* Link to the next note info. */ | ||||
}; | }; | ||||
TAILQ_HEAD(note_info_list, note_info); | TAILQ_HEAD(note_info_list, note_info); | ||||
extern int compress_user_cores; | extern int compress_user_cores; | ||||
extern int compress_user_cores_level; | extern int compress_user_cores_level; | ||||
static void cb_put_phdr(vm_map_entry_t, void *); | static void cb_put_phdr(vm_map_entry_t, void *); | ||||
static void cb_size_segment(vm_map_entry_t, void *); | static void cb_size_segment(vm_map_entry_t, void *); | ||||
static void each_dumpable_segment(struct thread *, segment_callback, void *, | static void each_dumpable_segment(struct thread *, segment_callback, void *, | ||||
int); | int); | ||||
static int __elfN(corehdr)(struct coredump_params *, int, void *, size_t, | static int __elfN(corehdr)(struct coredump_params *, int, void *, size_t, | ||||
struct note_info_list *, size_t, int); | struct note_info_list *, size_t, int); | ||||
static void __elfN(prepare_notes)(struct thread *, struct note_info_list *, | static void __elfN(putnote)(struct thread *td, struct note_info *, struct sbuf *); | ||||
size_t *); | |||||
static void __elfN(putnote)(struct note_info *, struct sbuf *); | |||||
static size_t register_note(struct note_info_list *, int, outfunc_t, void *); | |||||
static void __elfN(note_fpregset)(void *, struct sbuf *, size_t *); | static void __elfN(note_fpregset)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *); | static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_prstatus)(void *, struct sbuf *, size_t *); | static void __elfN(note_prstatus)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_threadmd)(void *, struct sbuf *, size_t *); | static void __elfN(note_threadmd)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_thrmisc)(void *, struct sbuf *, size_t *); | static void __elfN(note_thrmisc)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_ptlwpinfo)(void *, struct sbuf *, size_t *); | static void __elfN(note_ptlwpinfo)(void *, struct sbuf *, size_t *); | ||||
static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *); | static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *); | ||||
Show All 9 Lines | |||||
static int | static int | ||||
core_compressed_write(void *base, size_t len, off_t offset, void *arg) | core_compressed_write(void *base, size_t len, off_t offset, void *arg) | ||||
{ | { | ||||
return (core_write((struct coredump_params *)arg, base, len, offset, | return (core_write((struct coredump_params *)arg, base, len, offset, | ||||
UIO_SYSSPACE, NULL)); | UIO_SYSSPACE, NULL)); | ||||
} | } | ||||
int | int | ||||
kib: Why do you need __elfN mangling for this and other routines? Move them out of imgact_elf.c… | |||||
__elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) | __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) | ||||
{ | { | ||||
struct ucred *cred = td->td_ucred; | struct ucred *cred = td->td_ucred; | ||||
int compm, error = 0; | int compm, error = 0; | ||||
struct sseg_closure seginfo; | struct sseg_closure seginfo; | ||||
struct note_info_list notelst; | struct note_info_list notelst; | ||||
struct coredump_params params; | struct coredump_params params; | ||||
struct note_info *ninfo; | struct note_info *ninfo; | ||||
void *hdr, *tmpbuf; | void *hdr, *tmpbuf; | ||||
size_t hdrsize, notesz, coresize; | size_t hdrsize, notesz, coresize; | ||||
hdr = NULL; | hdr = NULL; | ||||
tmpbuf = NULL; | tmpbuf = NULL; | ||||
TAILQ_INIT(¬elst); | TAILQ_INIT(¬elst); | ||||
/* Size the program segments. */ | /* Size the program segments. */ | ||||
__elfN(size_segments)(td, &seginfo, flags); | __elfN(size_segments)(td, &seginfo, flags); | ||||
/* | /* | ||||
* Collect info about the core file header area. | * Collect info about the core file header area. | ||||
*/ | */ | ||||
hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count); | hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count); | ||||
if (seginfo.count + 1 >= PN_XNUM) | if (seginfo.count + 1 >= PN_XNUM) | ||||
hdrsize += sizeof(Elf_Shdr); | hdrsize += sizeof(Elf_Shdr); | ||||
__elfN(prepare_notes)(td, ¬elst, ¬esz); | td->td_proc->p_sysent->sv_elf_core_prepare_notes(td, ¬elst, ¬esz); | ||||
coresize = round_page(hdrsize + notesz) + seginfo.size; | coresize = round_page(hdrsize + notesz) + seginfo.size; | ||||
/* Set up core dump parameters. */ | /* Set up core dump parameters. */ | ||||
params.offset = 0; | params.offset = 0; | ||||
params.active_cred = cred; | params.active_cred = cred; | ||||
params.file_cred = NOCRED; | params.file_cred = NOCRED; | ||||
params.td = td; | params.td = td; | ||||
params.vp = vp; | params.vp = vp; | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | __elfN(corehdr)(struct coredump_params *p, int numsegs, void *hdr, | ||||
bzero(hdr, hdrsize); | bzero(hdr, hdrsize); | ||||
__elfN(puthdr)(p->td, hdr, hdrsize, numsegs, notesz, flags); | __elfN(puthdr)(p->td, hdr, hdrsize, numsegs, notesz, flags); | ||||
sb = sbuf_new(NULL, NULL, CORE_BUF_SIZE, SBUF_FIXEDLEN); | sb = sbuf_new(NULL, NULL, CORE_BUF_SIZE, SBUF_FIXEDLEN); | ||||
sbuf_set_drain(sb, sbuf_drain_core_output, p); | sbuf_set_drain(sb, sbuf_drain_core_output, p); | ||||
sbuf_start_section(sb, NULL); | sbuf_start_section(sb, NULL); | ||||
sbuf_bcat(sb, hdr, hdrsize); | sbuf_bcat(sb, hdr, hdrsize); | ||||
TAILQ_FOREACH(ninfo, notelst, link) | TAILQ_FOREACH(ninfo, notelst, link) | ||||
__elfN(putnote)(ninfo, sb); | __elfN(putnote)(p->td, ninfo, sb); | ||||
/* Align up to a page boundary for the program segments. */ | /* Align up to a page boundary for the program segments. */ | ||||
sbuf_end_section(sb, -1, PAGE_SIZE, 0); | sbuf_end_section(sb, -1, PAGE_SIZE, 0); | ||||
error = sbuf_finish(sb); | error = sbuf_finish(sb); | ||||
sbuf_delete(sb); | sbuf_delete(sb); | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | void | ||||
__elfN(prepare_notes)(struct thread *td, struct note_info_list *list, | __elfN(prepare_notes)(struct thread *td, struct note_info_list *list, | ||||
size_t *sizep) | size_t *sizep) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
struct thread *thr; | struct thread *thr; | ||||
size_t size; | size_t size; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
size = 0; | size = 0; | ||||
size += register_note(list, NT_PRPSINFO, __elfN(note_prpsinfo), p); | size += __elfN(register_note)(td, list, NT_PRPSINFO, __elfN(note_prpsinfo), p); | ||||
/* | /* | ||||
* To have the debugger select the right thread (LWP) as the initial | * To have the debugger select the right thread (LWP) as the initial | ||||
* thread, we dump the state of the thread passed to us in td first. | * thread, we dump the state of the thread passed to us in td first. | ||||
* This is the thread that causes the core dump and thus likely to | * This is the thread that causes the core dump and thus likely to | ||||
* be the right thread one wants to have selected in the debugger. | * be the right thread one wants to have selected in the debugger. | ||||
*/ | */ | ||||
thr = td; | thr = td; | ||||
while (thr != NULL) { | while (thr != NULL) { | ||||
size += register_note(list, NT_PRSTATUS, | size += __elfN(register_note)(td, list, NT_PRSTATUS, | ||||
__elfN(note_prstatus), thr); | __elfN(note_prstatus), thr); | ||||
size += register_note(list, NT_FPREGSET, | size += __elfN(register_note)(td, list, NT_FPREGSET, | ||||
__elfN(note_fpregset), thr); | __elfN(note_fpregset), thr); | ||||
size += register_note(list, NT_THRMISC, | size += __elfN(register_note)(td, list, NT_THRMISC, | ||||
__elfN(note_thrmisc), thr); | __elfN(note_thrmisc), thr); | ||||
size += register_note(list, NT_PTLWPINFO, | size += __elfN(register_note)(td, list, NT_PTLWPINFO, | ||||
__elfN(note_ptlwpinfo), thr); | __elfN(note_ptlwpinfo), thr); | ||||
size += register_note(list, -1, | size += __elfN(register_note)(td, list, -1, | ||||
__elfN(note_threadmd), thr); | __elfN(note_threadmd), thr); | ||||
thr = (thr == td) ? TAILQ_FIRST(&p->p_threads) : | thr = (thr == td) ? TAILQ_FIRST(&p->p_threads) : | ||||
TAILQ_NEXT(thr, td_plist); | TAILQ_NEXT(thr, td_plist); | ||||
if (thr == td) | if (thr == td) | ||||
thr = TAILQ_NEXT(thr, td_plist); | thr = TAILQ_NEXT(thr, td_plist); | ||||
} | } | ||||
size += register_note(list, NT_PROCSTAT_PROC, | size += __elfN(register_note)(td, list, NT_PROCSTAT_PROC, | ||||
__elfN(note_procstat_proc), p); | __elfN(note_procstat_proc), p); | ||||
size += register_note(list, NT_PROCSTAT_FILES, | size += __elfN(register_note)(td, list, NT_PROCSTAT_FILES, | ||||
note_procstat_files, p); | note_procstat_files, p); | ||||
size += register_note(list, NT_PROCSTAT_VMMAP, | size += __elfN(register_note)(td, list, NT_PROCSTAT_VMMAP, | ||||
note_procstat_vmmap, p); | note_procstat_vmmap, p); | ||||
size += register_note(list, NT_PROCSTAT_GROUPS, | size += __elfN(register_note)(td, list, NT_PROCSTAT_GROUPS, | ||||
note_procstat_groups, p); | note_procstat_groups, p); | ||||
size += register_note(list, NT_PROCSTAT_UMASK, | size += __elfN(register_note)(td, list, NT_PROCSTAT_UMASK, | ||||
note_procstat_umask, p); | note_procstat_umask, p); | ||||
size += register_note(list, NT_PROCSTAT_RLIMIT, | size += __elfN(register_note)(td, list, NT_PROCSTAT_RLIMIT, | ||||
note_procstat_rlimit, p); | note_procstat_rlimit, p); | ||||
size += register_note(list, NT_PROCSTAT_OSREL, | size += __elfN(register_note)(td, list, NT_PROCSTAT_OSREL, | ||||
note_procstat_osrel, p); | note_procstat_osrel, p); | ||||
size += register_note(list, NT_PROCSTAT_PSSTRINGS, | size += __elfN(register_note)(td, list, NT_PROCSTAT_PSSTRINGS, | ||||
__elfN(note_procstat_psstrings), p); | __elfN(note_procstat_psstrings), p); | ||||
size += register_note(list, NT_PROCSTAT_AUXV, | size += __elfN(register_note)(td, list, NT_PROCSTAT_AUXV, | ||||
__elfN(note_procstat_auxv), p); | __elfN(note_procstat_auxv), p); | ||||
*sizep = size; | *sizep = size; | ||||
} | } | ||||
void | void | ||||
__elfN(puthdr)(struct thread *td, void *hdr, size_t hdrsize, int numsegs, | __elfN(puthdr)(struct thread *td, void *hdr, size_t hdrsize, int numsegs, | ||||
size_t notesz, int flags) | size_t notesz, int flags) | ||||
{ | { | ||||
Elf_Ehdr *ehdr; | Elf_Ehdr *ehdr; | ||||
Elf_Phdr *phdr; | Elf_Phdr *phdr; | ||||
Elf_Shdr *shdr; | Elf_Shdr *shdr; | ||||
struct phdr_closure phc; | struct phdr_closure phc; | ||||
ehdr = (Elf_Ehdr *)hdr; | ehdr = (Elf_Ehdr *)hdr; | ||||
ehdr->e_ident[EI_MAG0] = ELFMAG0; | ehdr->e_ident[EI_MAG0] = ELFMAG0; | ||||
ehdr->e_ident[EI_MAG1] = ELFMAG1; | ehdr->e_ident[EI_MAG1] = ELFMAG1; | ||||
ehdr->e_ident[EI_MAG2] = ELFMAG2; | ehdr->e_ident[EI_MAG2] = ELFMAG2; | ||||
ehdr->e_ident[EI_MAG3] = ELFMAG3; | ehdr->e_ident[EI_MAG3] = ELFMAG3; | ||||
ehdr->e_ident[EI_CLASS] = ELF_CLASS; | ehdr->e_ident[EI_CLASS] = ELF_CLASS; | ||||
ehdr->e_ident[EI_DATA] = ELF_DATA; | ehdr->e_ident[EI_DATA] = ELF_DATA; | ||||
ehdr->e_ident[EI_VERSION] = EV_CURRENT; | ehdr->e_ident[EI_VERSION] = EV_CURRENT; | ||||
ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | ehdr->e_ident[EI_OSABI] = td->td_proc->p_sysent->sv_elf_core_osabi; | ||||
Not Done Inline ActionsI think this should be yet another sv_XXX method. kib: I think this should be yet another sv_XXX method. | |||||
Done Inline ActionsWhy? We're already calling this through this indirection (as sv_coredump); I don't see the point of adding more. Also, another ABI - if it ever happens - might need different tweaks here. trasz: Why? We're already calling this through this indirection (as sv_coredump); I don't see the… | |||||
Not Done Inline ActionsFor me, your reply sounds as an additional strong argument pro change this to sv_XXX method. Exactly because this part is per-ABI. The fact that it is called through sv_coredump does not matter, since you ended up in the shared code. kib: For me, your reply sounds as an additional strong argument pro change this to sv_XXX method. | |||||
Done Inline ActionsThis isn't per-ABI - it's ABI-specific. In other words, one can expect each ABI to require this kind of quirk, but not this particular one, so we would be adding more and more sv_whatever variables to control each of them. trasz: This isn't per-ABI - it's ABI-specific. In other words, one can expect each ABI to require… | |||||
Done Inline ActionsI think my main problem here is that adding another sv_variable makes things harder to understand (more indirection) and more boilerplate'y for no good reason - it won't make the code cleaner, shorter, or more flexible. trasz: I think my main problem here is that adding another sv_variable makes things harder to… | |||||
Not Done Inline ActionsOf course it makes the code cleaner, and we might argue about flexibility. But not having the FreeBSD ABI coredump code to know/care about other ABIs is the good design by definition. Also, I do not get the argument that some ABIs would need to do more specializations there. If the differences are large, ABI would provide more then one sysent classes, if not, it would handle it internally. But even more then, I do not want to contaminate the base FreeBSD code with the irrelevant details to handle foreign ABIs. kib: Of course it makes the code cleaner, and we might argue about flexibility. But not having the… | |||||
Done Inline ActionsOkay, what do you think about this instead? It avoids having any Linux-specific code in the common path, is simple, flexible, and avoids introducing another sysent entry. trasz: Okay, what do you think about this instead? It avoids having any Linux-specific code in the… | |||||
ehdr->e_ident[EI_ABIVERSION] = 0; | ehdr->e_ident[EI_ABIVERSION] = 0; | ||||
ehdr->e_ident[EI_PAD] = 0; | ehdr->e_ident[EI_PAD] = 0; | ||||
ehdr->e_type = ET_CORE; | ehdr->e_type = ET_CORE; | ||||
ehdr->e_machine = td->td_proc->p_elf_machine; | ehdr->e_machine = td->td_proc->p_elf_machine; | ||||
ehdr->e_version = EV_CURRENT; | ehdr->e_version = EV_CURRENT; | ||||
ehdr->e_entry = 0; | ehdr->e_entry = 0; | ||||
ehdr->e_phoff = sizeof(Elf_Ehdr); | ehdr->e_phoff = sizeof(Elf_Ehdr); | ||||
ehdr->e_flags = td->td_proc->p_elf_flags; | ehdr->e_flags = td->td_proc->p_elf_flags; | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | __elfN(puthdr)(struct thread *td, void *hdr, size_t hdrsize, int numsegs, | ||||
phdr++; | phdr++; | ||||
/* All the writable segments from the program. */ | /* All the writable segments from the program. */ | ||||
phc.phdr = phdr; | phc.phdr = phdr; | ||||
phc.offset = round_page(hdrsize + notesz); | phc.offset = round_page(hdrsize + notesz); | ||||
each_dumpable_segment(td, cb_put_phdr, &phc, flags); | each_dumpable_segment(td, cb_put_phdr, &phc, flags); | ||||
} | } | ||||
static size_t | size_t | ||||
register_note(struct note_info_list *list, int type, outfunc_t out, void *arg) | __elfN(register_note)(struct thread *td, struct note_info_list *list, | ||||
Done Inline ActionsCan you change the interface to add either struct sysentvec *sv or struct thread *td as the argument, to avoid referencing curproc there? I know that coredump code have more dependencies on the context so it cannot dump remote process, but I do not want to introduce new deps. kib: Can you change the interface to add either struct sysentvec *sv or struct thread *td as the… | |||||
int type, outfunc_t out, void *arg) | |||||
{ | { | ||||
const struct sysentvec *sv; | |||||
struct note_info *ninfo; | struct note_info *ninfo; | ||||
size_t size, notesize; | size_t size, notesize; | ||||
sv = td->td_proc->p_sysent; | |||||
size = 0; | size = 0; | ||||
out(arg, NULL, &size); | out(arg, NULL, &size); | ||||
ninfo = malloc(sizeof(*ninfo), M_TEMP, M_ZERO | M_WAITOK); | ninfo = malloc(sizeof(*ninfo), M_TEMP, M_ZERO | M_WAITOK); | ||||
ninfo->type = type; | ninfo->type = type; | ||||
ninfo->outfunc = out; | ninfo->outfunc = out; | ||||
ninfo->outarg = arg; | ninfo->outarg = arg; | ||||
ninfo->outsize = size; | ninfo->outsize = size; | ||||
TAILQ_INSERT_TAIL(list, ninfo, link); | TAILQ_INSERT_TAIL(list, ninfo, link); | ||||
if (type == -1) | if (type == -1) | ||||
return (size); | return (size); | ||||
notesize = sizeof(Elf_Note) + /* note header */ | notesize = sizeof(Elf_Note) + /* note header */ | ||||
roundup2(sizeof(FREEBSD_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) + | roundup2(strlen(sv->sv_elf_core_abi_vendor) + 1, ELF_NOTE_ROUNDSIZE) + | ||||
/* note name */ | /* note name */ | ||||
roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */ | roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */ | ||||
return (notesize); | return (notesize); | ||||
} | } | ||||
static size_t | static size_t | ||||
append_note_data(const void *src, void *dst, size_t len) | append_note_data(const void *src, void *dst, size_t len) | ||||
Show All 33 Lines | notesize = sizeof(Elf_Note) + /* note header */ | ||||
roundup2(sizeof(FREEBSD_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) + | roundup2(sizeof(FREEBSD_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) + | ||||
/* note name */ | /* note name */ | ||||
roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */ | roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */ | ||||
return (notesize); | return (notesize); | ||||
} | } | ||||
static void | static void | ||||
__elfN(putnote)(struct note_info *ninfo, struct sbuf *sb) | __elfN(putnote)(struct thread *td, struct note_info *ninfo, struct sbuf *sb) | ||||
Not Done Inline ActionsSame (please add td or sv arg)/ kib: Same (please add td or sv arg)/ | |||||
{ | { | ||||
Elf_Note note; | Elf_Note note; | ||||
const struct sysentvec *sv; | |||||
ssize_t old_len, sect_len; | ssize_t old_len, sect_len; | ||||
size_t new_len, descsz, i; | size_t new_len, descsz, i; | ||||
if (ninfo->type == -1) { | if (ninfo->type == -1) { | ||||
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); | ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); | ||||
return; | return; | ||||
} | } | ||||
note.n_namesz = sizeof(FREEBSD_ABI_VENDOR); | sv = td->td_proc->p_sysent; | ||||
note.n_namesz = strlen(sv->sv_elf_core_abi_vendor) + 1; | |||||
note.n_descsz = ninfo->outsize; | note.n_descsz = ninfo->outsize; | ||||
note.n_type = ninfo->type; | note.n_type = ninfo->type; | ||||
sbuf_bcat(sb, ¬e, sizeof(note)); | sbuf_bcat(sb, ¬e, sizeof(note)); | ||||
sbuf_start_section(sb, &old_len); | sbuf_start_section(sb, &old_len); | ||||
sbuf_bcat(sb, FREEBSD_ABI_VENDOR, sizeof(FREEBSD_ABI_VENDOR)); | sbuf_bcat(sb, sv->sv_elf_core_abi_vendor, | ||||
strlen(sv->sv_elf_core_abi_vendor) + 1); | |||||
sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); | sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); | ||||
if (note.n_descsz == 0) | if (note.n_descsz == 0) | ||||
return; | return; | ||||
sbuf_start_section(sb, &old_len); | sbuf_start_section(sb, &old_len); | ||||
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); | ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); | ||||
sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); | sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); | ||||
if (sect_len < 0) | if (sect_len < 0) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 712 Lines • Show Last 20 Lines |
Why do you need __elfN mangling for this and other routines? Move them out of imgact_elf.c, perhaps into kern_exec.c Do it as a preliminary review