Re: crash of 32-bit powerpc -r347549 kernel built via system-clang-8, _init_tls is where the initial DIAGNOSTICS-reported SIGSEGV happens

Mark Millard via freebsd-ppc <[email protected]>
Newsgroups gmane.os.freebsd.devel.ppc,gmane.os.freebsd.devel.hackers
Message-ID <[email protected]>
[Never mind: I found exec_setregs /usr/src/sys/powerpc/powerpc/exec_machdep.c
and were it is used.]

On 2019-Jun-9, at 01:49, Mark Millard <marklmi at yahoo.com> wrote:


> So far I've not been able to find the code that is supposed
> to establish the value of environ in /sbin/init as matching
> the value of arginfo->ps_envstr from the exec_copyout_strings
> use by do_execve in the kernel.
> 
> Anyone know where to point me to for what I seem to have
> missed?
> 
> The issue driving the question is having the *sp++ in
> _init_tls code below get SIGSEGV on 32-bit FreeBSD when
> built via system-clang-8 and devel/powerpc64-binutils:
> 
>       sp = (Elf_Addr *) environ;
>       while (*sp++ != 0)
>               ;
> 
> 
> The below is relevant detail that I've found.
> 
> _start in /sbin/init 's instance of lib/csu/powerpc/crt1.c
> calls _init_tls that is from lib/libc/gen/tls.c but first
> might assign to environ :
> 
> . . .
> #include "ignore_init.c"
> . . .
> void
> _start(int argc, char **argv, char **env,
>    const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void),
>    struct ps_strings *ps_strings)
> {
> 
> 
>        handle_argv(argc, argv, env);
> 
>        if (ps_strings != (struct ps_strings *)0)
>                __ps_strings = ps_strings;
> 
>        if (&_DYNAMIC != NULL)
>                atexit(cleanup);
>        else
>                _init_tls();
> 
> #ifdef GCRT
>        atexit(_mcleanup);
>        monstartup(&eprol, &etext);
> #endif
> 
>        handle_static_init(argc, argv, env);
>        exit(main(argc, argv, env));
> }
> 
> lib/csu/common/ignore_init.c has:
> 
> char **environ;
> . . .
> static inline void
> handle_argv(int argc, char *argv[], char **env)
> {
>        const char *s;
> 
>        if (environ == NULL)
>                environ = env;
>        if (argc > 0 && argv[0] != NULL) {
>                __progname = argv[0];
>                for (s = __progname; *s != '\0'; s++) {
>                        if (*s == '/')
>                                __progname = s + 1;
>                }
>        }
> }
> 
> So _start's char**env argument might be used to assign
> environ. But either way I've not managed to find the
> binding to the kernel exec_copyout_strings operation.
> 
> _init_tls has the *sp++ loop that I referenced earlier:
> 
> extern char **environ;
> 
> void
> _init_tls(void)
> {
> #ifndef PIC
>       Elf_Addr *sp;
>       Elf_Auxinfo *aux, *auxp;
>       Elf_Phdr *phdr;
>       size_t phent, phnum;
>       int i;
>       void *tls;
> 
>       sp = (Elf_Addr *) environ;
>       while (*sp++ != 0)
>               ;
> . . .
> 
> 
> On the kernel side for invoking /sbin/init is . . .
> 
> From /usr/src/sys/sys/imgact.h :
> 
> struct image_args {
>        char *buf;              /* pointer to string buffer */
>        void *bufkva;           /* cookie for string buffer KVA */
>        char *begin_argv;       /* beginning of argv in buf */
>        char *begin_envv;       /* (interal use only) beginning of envv in buf,
>                                 * access with exec_args_get_begin_envv(). */
>        char *endp;             /* current `end' pointer of arg & env strings */
>        char *fname;            /* pointer to filename of executable (system space) */
>        char *fname_buf;        /* pointer to optional malloc(M_TEMP) buffer */
>        int stringspace;        /* space left in arg & env buffer */
>        int argc;               /* count of argument strings */
>        int envc;               /* count of environment strings */
>        int fd;                 /* file descriptor of the executable */
>        struct filedesc *fdp;   /* new file descriptor table */
> };
> 
> do_execve from sys/kern/kern_exec.c has use, including envc
> but avoiding begin_envv (via starting from begin_argv):
> 
> static int
> do_execve(struct thread *td, struct image_args *args, struct mac *mac_p)
> {
> . . .
>        /*
>         * Copy out strings (args and env) and initialize stack base.
>         */
>        stack_base = (*p->p_sysent->sv_copyout_strings)(imgp);
> 
> 
> The exec_copyout_strings code (accessed via ->sv_copyout_strings)
> does
> 
>        stack_base = (register_t *)vectp;
> 
>        stringp = imgp->args->begin_argv;
>        argc = imgp->args->argc;
>        envc = imgp->args->envc;
> . . .
> 
>        /* a null vector table pointer separates the argp's from the envp's */
>        suword(vectp++, 0);
> 
>        suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
>        suword32(&arginfo->ps_nenvstr, envc);
> 
>        /*
>         * Fill in environment portion of vector table.
>         */
>        for (; envc > 0; --envc) {
>                suword(vectp++, (long)(intptr_t)destp);
>                while (*stringp++ != 0)
>                        destp++;
>                destp++;
>        }
> 
>        /* end of vector table is a null pointer */
>        suword(vectp, 0);
> . . .
> 
> (From what I've seen for /sbin/init being invoked, envc==0 .)
> 
> The use involves struct ps_strings from /usr/src/sys/sys/exec.h :
> 
> struct ps_strings {
>        char    **ps_argvstr;   /* first of 0 or more argument strings */
>        unsigned int ps_nargvstr; /* the number of argument strings */
>        char    **ps_envstr;    /* first of 0 or more environment strings */
>        unsigned int ps_nenvstr; /* the number of environment strings */
> };
> 
> 
> The initialization of the begin_envv and envc for much of
> the code seems to trace back to:
> 
> static void
> start_init(void *dummy)
> {
>        struct image_args args;
> . . .
>        while ((path = strsep(&tmp_init_path, ":")) != NULL) {
>                if (bootverbose)
>                        printf("start_init: trying %s\n", path);
> 
>                memset(&args, 0, sizeof(args));
> . . .


I found it:

/usr/src/sys/powerpc/powerpc/exec_machdep.c has
exec_setregs that is accessed (via sv_setregs).
This sets up arguments for _start .



===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)

_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ppc
To unsubscribe, send any mail to "[email protected]"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.