+static int
+init_syscall_symbol(struct library_symbol *libsym, const char *name)
+{
+ static struct library syscall_lib;
+
+ if (syscall_lib.protolib == NULL) {
+ struct protolib *protolib
+ = protolib_cache_load(&g_protocache, "syscalls", 0, 1);
+ if (protolib == NULL) {
+ fprintf(stderr, "Couldn't load system call prototypes:"
+ " %s.\n", strerror(errno));
+
+ /* Instead, get a fake one just so we can
+ * carry on, limping. */
+ protolib = malloc(sizeof *protolib);
+ if (protolib == NULL) {
+ fprintf(stderr, "Couldn't even allocate a fake "
+ "prototype library: %s.\n",
+ strerror(errno));
+ abort();
+ }
+ protolib_init(protolib);
+ }
+
+ assert(protolib != NULL);
+ if (library_init(&syscall_lib, LT_LIBTYPE_SYSCALL) < 0) {
+ fprintf(stderr, "Couldn't initialize system call "
+ "library: %s.\n", strerror(errno));
+ abort();
+ }
+
+ library_set_soname(&syscall_lib, "SYS", 0);
+ syscall_lib.protolib = protolib;
+ }
+
+ if (library_symbol_init(libsym, 0, name, 0, LS_TOPLT_NONE) < 0)
+ return -1;
+
+ libsym->lib = &syscall_lib;
+ return 0;
+}
+
+/* Account the unfinished functions on the call stack. */
+static void
+account_current_callstack(struct process *proc)
+{
+ if (! options.summary)
+ return;
+
+ struct timedelta spent[proc->callstack_depth];
+
+ size_t i;
+ for (i = 0; i < proc->callstack_depth; ++i) {
+ struct callstack_element *elem = &proc->callstack[i];
+ spent[i] = calc_time_spent(elem->enter_time);
+ }
+
+ for (i = 0; i < proc->callstack_depth; ++i) {
+ struct callstack_element *elem = &proc->callstack[i];
+ struct library_symbol syscall, *libsym = NULL;
+ if (elem->is_syscall) {
+ const char *name = sysname(proc, elem->c_un.syscall);
+ if (init_syscall_symbol(&syscall, name) >= 0)
+ libsym = &syscall;
+
+ } else {
+ libsym = elem->c_un.libfunc;
+ }
+
+ if (libsym != NULL) {
+ summary_account_call(libsym, spent[i]);
+
+ if (elem->is_syscall)
+ library_symbol_destroy(&syscall);
+ }
+ }
+}
+