Date: Sun, 9 Jun 2019 13:10:53 -0700 From: Mark Millard <marklmi@yahoo.com> To: FreeBSD Hackers <freebsd-hackers@freebsd.org>, FreeBSD PowerPC ML <freebsd-ppc@freebsd.org> Subject: Re: crash of 32-bit powerpc -r347549 kernel built via system-clang-8, _init_tls is where the initial DIAGNOSTICS-reported SIGSEGV happens Message-ID: <141293A3-0111-4E08-AA76-2F9DBBEA5A58@yahoo.com> In-Reply-To: <35F598E5-2400-4768-8B39-BC5F9B051443@yahoo.com> References: <8F272F27-0BC3-402A-810A-4608162F9EEE@yahoo.com> <35F598E5-2400-4768-8B39-BC5F9B051443@yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[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.
>=20
> Anyone know where to point me to for what I seem to have
> missed?
>=20
> 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:
>=20
> sp =3D (Elf_Addr *) environ;
> while (*sp++ !=3D 0)
> ;
>=20
>=20
> The below is relevant detail that I've found.
>=20
> _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 :
>=20
> . . .
> #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)
> {
>=20
>=20
> handle_argv(argc, argv, env);
>=20
> if (ps_strings !=3D (struct ps_strings *)0)
> __ps_strings =3D ps_strings;
>=20
> if (&_DYNAMIC !=3D NULL)
> atexit(cleanup);
> else
> _init_tls();
>=20
> #ifdef GCRT
> atexit(_mcleanup);
> monstartup(&eprol, &etext);
> #endif
>=20
> handle_static_init(argc, argv, env);
> exit(main(argc, argv, env));
> }
>=20
> lib/csu/common/ignore_init.c has:
>=20
> char **environ;
> . . .
> static inline void
> handle_argv(int argc, char *argv[], char **env)
> {
> const char *s;
>=20
> if (environ =3D=3D NULL)
> environ =3D env;
> if (argc > 0 && argv[0] !=3D NULL) {
> __progname =3D argv[0];
> for (s =3D __progname; *s !=3D '\0'; s++) {
> if (*s =3D=3D '/')
> __progname =3D s + 1;
> }
> }
> }
>=20
> 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.
>=20
> _init_tls has the *sp++ loop that I referenced earlier:
>=20
> extern char **environ;
>=20
> void
> _init_tls(void)
> {
> #ifndef PIC
> Elf_Addr *sp;
> Elf_Auxinfo *aux, *auxp;
> Elf_Phdr *phdr;
> size_t phent, phnum;
> int i;
> void *tls;
>=20
> sp =3D (Elf_Addr *) environ;
> while (*sp++ !=3D 0)
> ;
> . . .
>=20
>=20
> On the kernel side for invoking /sbin/init is . . .
>=20
> =46rom /usr/src/sys/sys/imgact.h :
>=20
> 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 */
> };
>=20
> do_execve from sys/kern/kern_exec.c has use, including envc
> but avoiding begin_envv (via starting from begin_argv):
>=20
> 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 =3D (*p->p_sysent->sv_copyout_strings)(imgp);
>=20
>=20
> The exec_copyout_strings code (accessed via ->sv_copyout_strings)
> does
>=20
> stack_base =3D (register_t *)vectp;
>=20
> stringp =3D imgp->args->begin_argv;
> argc =3D imgp->args->argc;
> envc =3D imgp->args->envc;
> . . .
>=20
> /* a null vector table pointer separates the argp's from the =
envp's */
> suword(vectp++, 0);
>=20
> suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
> suword32(&arginfo->ps_nenvstr, envc);
>=20
> /*
> * Fill in environment portion of vector table.
> */
> for (; envc > 0; --envc) {
> suword(vectp++, (long)(intptr_t)destp);
> while (*stringp++ !=3D 0)
> destp++;
> destp++;
> }
>=20
> /* end of vector table is a null pointer */
> suword(vectp, 0);
> . . .
>=20
> (=46rom what I've seen for /sbin/init being invoked, envc=3D=3D0 .)
>=20
> The use involves struct ps_strings from /usr/src/sys/sys/exec.h :
>=20
> 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 =
*/
> };
>=20
>=20
> The initialization of the begin_envv and envc for much of
> the code seems to trace back to:
>=20
> static void
> start_init(void *dummy)
> {
> struct image_args args;
> . . .
> while ((path =3D strsep(&tmp_init_path, ":")) !=3D NULL) {
> if (bootverbose)
> printf("start_init: trying %s\n", path);
>=20
> 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 .
=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?141293A3-0111-4E08-AA76-2F9DBBEA5A58>
