Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 2443ad8 in mainline


Ignore:
Timestamp:
2019-10-02T09:27:57Z (13 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
9dcf472
Parents:
6fa3a03
git-author:
Jiri Svoboda <jiri@…> (2019-10-01 17:23:52)
git-committer:
Jiri Svoboda <jiri@…> (2019-10-02 09:27:57)
Message:

Let trace not use the loader API directly

This fixes traced binaries crashing due to missing working directory
in PCB. It should also prevent similar problems in the future.

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/trace/trace.c

    r6fa3a03 r2443ad8  
    4747#include <mem.h>
    4848#include <str.h>
    49 #include <loader/loader.h>
    5049#include <io/console.h>
    5150#include <io/keycode.h>
     
    8685void thread_trace_start(uintptr_t thread_hash);
    8786
     87static char *cmd_path;
     88static char **cmd_args;
     89
    8890static task_id_t task_id;
    89 static loader_t *task_ldr;
    9091static bool task_wait_for;
    9192
     
    9394display_mask_t display_mask;
    9495
    95 static errno_t program_run_fibril(void *arg);
    9696static errno_t cev_fibril(void *arg);
    97 
    98 static void program_run(void)
    99 {
    100         fid_t fid;
    101 
    102         fid = fibril_create(program_run_fibril, NULL);
    103         if (fid == 0) {
    104                 printf("Error creating fibril\n");
    105                 exit(1);
    106         }
    107 
    108         fibril_add_ready(fid);
    109 }
    11097
    11198static void cev_fibril_start(void)
     
    122109}
    123110
    124 static errno_t program_run_fibril(void *arg)
    125 {
    126         errno_t rc;
    127 
    128         /*
    129          * This must be done in background as it will block until
    130          * we let the task reply to this call.
    131          */
    132         rc = loader_run(task_ldr);
     111static errno_t program_run(void)
     112{
     113        errno_t rc;
     114
     115        rc = task_spawnv_debug(&task_id, NULL, cmd_path,
     116            (const char *const *)cmd_args, &sess);
     117
     118        if (rc == ENOTSUP) {
     119                printf("You do not have userspace debugging support "
     120                    "compiled in the kernel.\n");
     121                printf("Compile kernel with 'Support for userspace debuggers' "
     122                    "(CONFIG_UDEBUG) enabled.\n");
     123        }
     124
    133125        if (rc != EOK) {
    134                 printf("Error running program\n");
    135                 exit(1);
    136         }
    137 
    138         task_ldr = NULL;
    139 
    140         printf("program_run_fibril exiting\n");
    141         return 0;
     126                printf("Error running program (%s)\n", str_error_name(rc));
     127                return rc;
     128        }
     129
     130        return EOK;
    142131}
    143132
    144133static errno_t connect_task(task_id_t task_id)
    145134{
    146         async_sess_t *ksess = async_connect_kbox(task_id);
    147 
    148         if (!ksess) {
    149                 if (errno == ENOTSUP) {
    150                         printf("You do not have userspace debugging support "
    151                             "compiled in the kernel.\n");
    152                         printf("Compile kernel with 'Support for userspace debuggers' "
    153                             "(CONFIG_UDEBUG) enabled.\n");
    154                         return errno;
    155                 }
    156 
    157                 printf("Error connecting\n");
    158                 printf("ipc_connect_task(%" PRIu64 ") -> %s ", task_id, str_error_name(errno));
    159                 return errno;
    160         }
    161 
    162         errno_t rc = udebug_begin(ksess);
    163         if (rc != EOK) {
    164                 printf("udebug_begin() -> %s\n", str_error_name(rc));
    165                 return rc;
    166         }
    167 
    168         rc = udebug_set_evmask(ksess, UDEBUG_EM_ALL);
     135        errno_t rc;
     136        bool debug_started = false;
     137
     138        if (sess == NULL) {
     139                sess = async_connect_kbox(task_id);
     140                if (sess == NULL) {
     141                        printf("Error connecting to task %" PRIu64 ".\n",
     142                            task_id);
     143                        goto error;
     144                }
     145
     146                rc = udebug_begin(sess);
     147                if (rc != EOK) {
     148                        printf("Error starting debug session.\n");
     149                        goto error;
     150                }
     151
     152                debug_started = true;
     153        }
     154
     155        rc = udebug_set_evmask(sess, UDEBUG_EM_ALL);
    169156        if (rc != EOK) {
    170157                printf("udebug_set_evmask(0x%x) -> %s\n ", UDEBUG_EM_ALL, str_error_name(rc));
     
    172159        }
    173160
    174         sess = ksess;
    175         return 0;
     161        return EOK;
     162error:
     163        if (debug_started)
     164                udebug_end(sess);
     165        if (sess != NULL)
     166                async_hangup(sess);
     167        return rc;
    176168}
    177169
     
    198190        printf("\ntotal of %zu threads\n", tb_needed / sizeof(uintptr_t));
    199191
    200         return 0;
     192        return EOK;
    201193}
    202194
     
    488480
    489481        printf("Finished tracing thread [%d].\n", thread_id);
    490         return 0;
     482        return EOK;
    491483}
    492484
     
    502494        }
    503495        fibril_add_ready(fid);
    504 }
    505 
    506 static loader_t *preload_task(const char *path, char **argv,
    507     task_id_t *task_id)
    508 {
    509         loader_t *ldr;
    510         errno_t rc;
    511 
    512         /* Spawn a program loader */
    513         ldr = loader_connect();
    514         if (ldr == NULL)
    515                 return NULL;
    516 
    517         /* Get task ID. */
    518         rc = loader_get_task_id(ldr, task_id);
    519         if (rc != EOK)
    520                 goto error;
    521 
    522         /* Send program. */
    523         rc = loader_set_program_path(ldr, path);
    524         if (rc != EOK)
    525                 goto error;
    526 
    527         /* Send arguments */
    528         rc = loader_set_args(ldr, (const char **) argv);
    529         if (rc != EOK)
    530                 goto error;
    531 
    532         /* Send default files */
    533         int fd_root;
    534         int fd_stdin;
    535         int fd_stdout;
    536         int fd_stderr;
    537 
    538         fd_root = vfs_root();
    539         if (fd_root >= 0) {
    540                 rc = loader_add_inbox(ldr, "root", fd_root);
    541                 vfs_put(fd_root);
    542                 if (rc != EOK)
    543                         goto error;
    544         }
    545 
    546         if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK)) {
    547                 rc = loader_add_inbox(ldr, "stdin", fd_stdin);
    548                 if (rc != EOK)
    549                         goto error;
    550         }
    551 
    552         if ((stdout != NULL) && (vfs_fhandle(stdout, &fd_stdout) == EOK)) {
    553                 rc = loader_add_inbox(ldr, "stdout", fd_stdout);
    554                 if (rc != EOK)
    555                         goto error;
    556         }
    557 
    558         if ((stderr != NULL) && (vfs_fhandle(stderr, &fd_stderr) == EOK)) {
    559                 rc = loader_add_inbox(ldr, "stderr", fd_stderr);
    560                 if (rc != EOK)
    561                         goto error;
    562         }
    563 
    564         /* Load the program. */
    565         rc = loader_load_program(ldr);
    566         if (rc != EOK)
    567                 goto error;
    568 
    569         /* Success */
    570         return ldr;
    571 
    572         /* Error exit */
    573 error:
    574         loader_abort(ldr);
    575         return NULL;
    576496}
    577497
     
    807727                                ++argv;
    808728                                task_id = strtol(*argv, &err_p, 10);
    809                                 task_ldr = NULL;
    810729                                task_wait_for = false;
    811730                                if (*err_p) {
     
    848767                printf("'%s'\n", *cp++);
    849768
    850         task_ldr = preload_task(*argv, argv, &task_id);
     769        cmd_path = *argv;
     770        cmd_args = argv;
    851771        task_wait_for = true;
    852772
     
    869789
    870790        main_init();
     791
     792        if (cmd_path != NULL)
     793                program_run();
    871794
    872795        rc = connect_task(task_id);
     
    877800
    878801        printf("Connected to task %" PRIu64 ".\n", task_id);
    879 
    880         if (task_ldr != NULL)
    881                 program_run();
    882802
    883803        cev_fibril_start();
  • uspace/lib/c/generic/loader.c

    r6fa3a03 r2443ad8  
    345345}
    346346
     347/** Instruct loader to execute the program and do not wait for reply.
     348 *
     349 * This function does not block even if the loaded task is stopped
     350 * for debugging.
     351 *
     352 * After using this function, no further operations can be performed
     353 * on the loader structure and it is deallocated.
     354 *
     355 * @param ldr Loader connection structure.
     356 *
     357 * @return Zero on success or an error code.
     358 *
     359 */
     360void loader_run_nowait(loader_t *ldr)
     361{
     362        async_exch_t *exch = async_exchange_begin(ldr->sess);
     363        async_msg_0(exch, LOADER_RUN);
     364        async_exchange_end(exch);
     365
     366        async_hangup(ldr->sess);
     367        free(ldr);
     368}
     369
    347370/** Cancel the loader session.
    348371 *
  • uspace/lib/c/generic/task.c

    r6fa3a03 r2443ad8  
    3535 */
    3636
     37#include <async.h>
    3738#include <task.h>
    3839#include <loader/loader.h>
     
    4647#include <ns.h>
    4748#include <stdlib.h>
     49#include <udebug.h>
    4850#include <libc.h>
    4951#include "private/ns.h"
     
    9496 * This is really just a convenience wrapper over the more complicated
    9597 * loader API. Arguments are passed as a null-terminated array of strings.
     98 * A debug session is created optionally.
    9699 *
    97100 * @param id   If not NULL, the ID of the task is stored here on success.
     
    100103 * @param path Pathname of the binary to execute.
    101104 * @param argv Command-line arguments.
    102  *
    103  * @return Zero on success or an error code.
    104  *
    105  */
    106 errno_t task_spawnv(task_id_t *id, task_wait_t *wait, const char *path,
    107     const char *const args[])
     105 * @param rsess   Place to store pointer to debug session or @c NULL
     106 *                not to start a debug session
     107 *
     108 * @return Zero on success or an error code.
     109 *
     110 */
     111errno_t task_spawnv_debug(task_id_t *id, task_wait_t *wait, const char *path,
     112    const char *const args[], async_sess_t **rsess)
    108113{
    109114        /* Send default files */
     
    125130        }
    126131
    127         return task_spawnvf(id, wait, path, args, fd_stdin, fd_stdout,
    128             fd_stderr);
     132        return task_spawnvf_debug(id, wait, path, args, fd_stdin, fd_stdout,
     133            fd_stderr, rsess);
    129134}
    130135
    131136/** Create a new task by running an executable from the filesystem.
     137 *
     138 * This is really just a convenience wrapper over the more complicated
     139 * loader API. Arguments are passed as a null-terminated array of strings.
     140 *
     141 * @param id   If not NULL, the ID of the task is stored here on success.
     142 * @param wait If not NULL, setup waiting for task's return value and store
     143 *             the information necessary for waiting here on success.
     144 * @param path Pathname of the binary to execute.
     145 * @param argv Command-line arguments.
     146 *
     147 * @return Zero on success or an error code.
     148 *
     149 */
     150errno_t task_spawnv(task_id_t *id, task_wait_t *wait, const char *path,
     151    const char *const args[])
     152{
     153        return task_spawnv_debug(id, wait, path, args, NULL);
     154}
     155
     156/** Create a new task by loading an executable from the filesystem.
    132157 *
    133158 * This is really just a convenience wrapper over the more complicated
    134159 * loader API. Arguments are passed as a null-terminated array of strings.
    135160 * Files are passed as null-terminated array of pointers to fdi_node_t.
     161 * A debug session is created optionally.
    136162 *
    137163 * @param id      If not NULL, the ID of the task is stored here on success.
    138  * @param wait    If not NULL, setup waiting for task's return value and store
     164 * @param wait    If not NULL, setup waiting for task's return value and store.
    139165 * @param path    Pathname of the binary to execute.
    140  * @param argv    Command-line arguments.
    141  * @param std_in  File to use as stdin.
    142  * @param std_out File to use as stdout.
    143  * @param std_err File to use as stderr.
    144  *
    145  * @return Zero on success or an error code.
    146  *
    147  */
    148 errno_t task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
    149     const char *const args[], int fd_stdin, int fd_stdout, int fd_stderr)
    150 {
     166 * @param argv    Command-line arguments
     167 * @param std_in  File to use as stdin
     168 * @param std_out File to use as stdout
     169 * @param std_err File to use as stderr
     170 * @param rsess   Place to store pointer to debug session or @c NULL
     171 *                not to start a debug session
     172 *
     173 * @return Zero on success or an error code
     174 *
     175 */
     176errno_t task_spawnvf_debug(task_id_t *id, task_wait_t *wait,
     177    const char *path, const char *const args[], int fd_stdin, int fd_stdout,
     178    int fd_stderr, async_sess_t **rsess)
     179{
     180        async_sess_t *ksess = NULL;
     181
    151182        /* Connect to a program loader. */
    152183        loader_t *ldr = loader_connect();
     
    217248        }
    218249
    219         /* Run it. */
    220         rc = loader_run(ldr);
    221         if (rc != EOK)
    222                 goto error;
     250        /* Start a debug session if requested */
     251        if (rsess != NULL) {
     252                ksess = async_connect_kbox(task_id);
     253                if (ksess == NULL) {
     254                        /* Most likely debugging support is not compiled in */
     255                        rc = ENOTSUP;
     256                        goto error;
     257                }
     258
     259                rc = udebug_begin(ksess);
     260                if (rc != EOK)
     261                        goto error;
     262
     263                /*
     264                 * Run it, not waiting for response. It would never come
     265                 * as the loader is stopped.
     266                 */
     267                loader_run_nowait(ldr);
     268        } else {
     269                /* Run it. */
     270                rc = loader_run(ldr);
     271                if (rc != EOK)
     272                        goto error;
     273        }
    223274
    224275        /* Success */
    225276        if (id != NULL)
    226277                *id = task_id;
    227 
     278        if (rsess != NULL)
     279                *rsess = ksess;
    228280        return EOK;
    229281
    230282error:
     283        if (ksess != NULL)
     284                async_hangup(ksess);
    231285        if (wait_initialized)
    232286                task_cancel_wait(wait);
     
    235289        loader_abort(ldr);
    236290        return rc;
     291}
     292
     293/** Create a new task by running an executable from the filesystem.
     294 *
     295 * Arguments are passed as a null-terminated array of strings.
     296 * Files are passed as null-terminated array of pointers to fdi_node_t.
     297 *
     298 * @param id      If not NULL, the ID of the task is stored here on success.
     299 * @param wait    If not NULL, setup waiting for task's return value and store.
     300 * @param path    Pathname of the binary to execute
     301 * @param argv    Command-line arguments
     302 * @param std_in  File to use as stdin
     303 * @param std_out File to use as stdout
     304 * @param std_err File to use as stderr
     305 *
     306 * @return Zero on success or an error code.
     307 *
     308 */
     309errno_t task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
     310    const char *const args[], int fd_stdin, int fd_stdout, int fd_stderr)
     311{
     312        return task_spawnvf_debug(id, wait, path, args, fd_stdin, fd_stdout,
     313            fd_stderr, NULL);
    237314}
    238315
  • uspace/lib/c/include/loader/loader.h

    r6fa3a03 r2443ad8  
    5353extern errno_t loader_load_program(loader_t *);
    5454extern errno_t loader_run(loader_t *);
     55extern void loader_run_nowait(loader_t *);
    5556extern void loader_abort(loader_t *);
    5657
  • uspace/lib/c/include/task.h

    r6fa3a03 r2443ad8  
    3636#define _LIBC_TASK_H_
    3737
     38#include <async.h>
    3839#include <stdint.h>
    3940#include <stdarg.h>
     
    5657extern errno_t task_spawnv(task_id_t *, task_wait_t *, const char *path,
    5758    const char *const []);
     59extern errno_t task_spawnv_debug(task_id_t *, task_wait_t *, const char *path,
     60    const char *const [], async_sess_t **);
    5861extern errno_t task_spawnvf(task_id_t *, task_wait_t *, const char *path,
    5962    const char *const [], int, int, int);
     63extern errno_t task_spawnvf_debug(task_id_t *, task_wait_t *, const char *path,
     64    const char *const [], int, int, int, async_sess_t **);
    6065extern errno_t task_spawn(task_id_t *, task_wait_t *, const char *path, int,
    6166    va_list ap);
Note: See TracChangeset for help on using the changeset viewer.