/******************************************************************************* Process a (file system) pathname (a file, directory or "other"). *******************************************************************************/ void process_path(char *pathname, regex_t *extregexpptr, int recursiondepth) { struct stat statinfo; if (recursiondepth == 0) { trim_trailing_slashes(pathname); } if (!regularfileflag && !directoryflag && !otherobjectflag) { fprintf(stderr, "No output target types requested for '%s'!\n",pathname); returncode = 1; return; } if (lstat(pathname, &statinfo) == -1) { fprintf(stderr, "process_path: Cannot access '%s'\n", pathname); returncode = 1; return; } if (S_ISREG(statinfo.st_mode)) { if (regularfileflag) { process_object(pathname, extregexpptr); } } else if (S_ISDIR(statinfo.st_mode)) { if (directoryflag) { process_object(pathname, extregexpptr); } if (recursiondepth == 0 || (recursiveflag && recursiondepth <= maxrecursiondepth)) { process_directory(pathname, extregexpptr, recursiondepth); } } else if (otherobjectflag) { process_object(pathname, extregexpptr); } }
static int loop(struct walker *walker) { struct object_list *elem; while (process_queue) { struct object *obj = process_queue->item; elem = process_queue; process_queue = elem->next; free(elem); if (!process_queue) process_queue_end = &process_queue; /* If we are not scanning this object, we placed it in * the queue because we needed to fetch it first. */ if (! (obj->flags & TO_SCAN)) { if (walker->fetch(walker, obj->sha1)) { report_missing(obj); return -1; } } if (!obj->type) parse_object(obj->sha1); if (process_object(walker, obj)) return -1; } return 0; }
int main () { by_reference(); std::cout << std::endl; by_value_copy(); std::cout << std::endl; by_value_move(); std::cout << std::endl; by_value_temp_move(); std::cout << std::endl; by_value_temp_move_rvo(); std::cout << std::endl; some_method_by_reference(A(S(std::string("cool string")))); std::cout << std::endl; some_method_by_reference(B(S(std::string("cool string")))); std::cout << std::endl; emplace_into_vector(); std::cout << std::endl; process_object(B(get_string())); std::cout << std::endl; return 0; }
static void process_value(json_value* value, int depth) { int j; if (value == NULL) { return; } if (value->type != json_object) { print_depth_shift(depth); } DEBUG("PROCESSBALUE\n"); switch (value->type) { case json_none: DEBUG("none\n"); break; case json_object: process_object(value, depth+1); break; case json_array: process_array(value, depth+1); break; case json_integer: DEBUG("int: %ld\n", value->u.integer); break; case json_double: DEBUG("double: %f\n", value->u.dbl); break; case json_string: DEBUG("string: %s\n", value->u.string.ptr); break; case json_boolean: DEBUG("bool: %d\n", value->u.boolean); break; case json_null: DEBUG("JSON parse NULL\n"); break; } }
void start_job(File_t *object) { check_connection(); pid_t p; if (n_jobs == parallel_max) { wait_for_job(); } p = fork(); if (p < 0) { Error("fork failed"); } else if (p == 0) { bool status = process_object(object); if (!status) { *connection_broken = 1; } exit(1); } ++n_jobs; }
static void reload (an_object_file_ptr pobj, string path) { string old_name = pobj->name; unsigned old_name_index = pobj->name_ndx; int fd; unread_sections (pobj); unread_obj (pobj, FALSE); BZERO (pobj, sizeof(an_object_file)); pobj->other_name = old_name; pobj->other_name_ndx = old_name_index; pobj->name = path; pobj->name_ndx = string_find_offset(path); /* copied from pass1 */ fd = open_file (path, TRUE, FALSE, 0); if (!use_mmap) pobj->access_method = AM_READ; pobj->ftype = read_headers (pobj, fd, FALSE); LD_ASSERT (pobj->ftype == FT_OBJ, thisfile, "incorrect file type from back end"); add_object (pobj); msg(ER_DEFAULT /* ER_VERBOSE */ , ERN_LOAD_OBJ, num_objects_linked, pobj->name); if (bsdmap) printf("%s\n", pobj->other_name); process_object (pobj); if (optsym[OPTSYM_MDEPEND].num) update_make_depend (pobj->other_name); unread_sections (pobj); close (fd); delay_load = DL_DEFAULT; if (hides != HS_IGNORE) { hides = HS_DEFAULT; } } /* reload */
/* * Get the linkmap from the dynlinker. Try to load kernel modules * from all objects in the linkmap. */ void rumpuser_dl_bootstrap(rump_modinit_fn domodinit, rump_symload_fn symload, rump_compload_fn compload) { struct link_map *map, *origmap, *mainmap; void *mainhandle; int error; mainhandle = dlopen(NULL, RTLD_NOW); if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) { fprintf(stderr, "warning: rumpuser module bootstrap " "failed: %s\n", dlerror()); return; } origmap = mainmap; /* * Process last->first because that's the most probable * order for dependencies */ for (; origmap->l_next; origmap = origmap->l_next) continue; /* * Build symbol table to hand to the rump kernel. Do this by * iterating over all rump libraries and collecting symbol * addresses and relocation info. */ error = 0; for (map = origmap; map && !error; map = map->l_prev) { if (strstr(map->l_name, "librump") != NULL || map == mainmap) error = getsymbols(map, map == mainmap); } if (error == 0) { void *trimmedsym, *trimmedstr; /* * Allocate optimum-sized memory for storing tables * and feed to kernel. If memory allocation fails, * just give the ones with extra context (although * I'm pretty sure we'll die moments later due to * memory running out). */ if ((trimmedsym = malloc(symtaboff)) != NULL) { memcpy(trimmedsym, symtab, symtaboff); } else { trimmedsym = symtab; symtab = NULL; } if ((trimmedstr = malloc(strtaboff)) != NULL) { memcpy(trimmedstr, strtab, strtaboff); } else { trimmedstr = strtab; strtab = NULL; } symload(trimmedsym, symtaboff, trimmedstr, strtaboff); } free(symtab); free(strtab); /* * Next, load modules and components. * * Simply loop through all objects, ones unrelated to rump kernels * will not contain link_set_rump_components (well, not including * "sabotage", but that needs to be solved at another level anyway). */ for (map = origmap; map; map = map->l_prev) { void *handle; if (map == mainmap) { handle = mainhandle; } else { handle = dlopen(map->l_name, RTLD_LAZY); if (handle == NULL) continue; } process_object(handle, domodinit, compload); if (map != mainmap) dlclose(handle); } }
int main(int argc, char **argv) { char config_file_path[256]; opt_filename = NULL; opt_url = NULL; fetch_all = false; test_mode = false; verbose = false; opt_insecure = false; used_insecure = false; strcpy(config_file_path, "/etc/openrail.conf"); word usage = false; int c; while ((c = getopt (argc, argv, ":c:u:f:tpih")) != -1) switch (c) { case 'c': strcpy(config_file_path, optarg); break; case 'u': if(!opt_filename) opt_url = optarg; break; case 'f': if(!opt_url) opt_filename = optarg; break; case 'a': fetch_all = true; break; case 't': test_mode = true; break; case 'p': verbose = true; break; case 'i': opt_insecure = true; break; case 'h': usage = true; break; case ':': break; case '?': default: usage = true; break; } char * config_fail; if((config_fail = load_config(config_file_path))) { printf("Failed to read config file \"%s\": %s\n", config_file_path, config_fail); usage = true; } if(usage) { printf("%s %s Usage: %s [-c /path/to/config/file.conf] [-u <url> | -f <path> | -a] [-t | -r] [-p][-i]\n", NAME, BUILD, argv[0]); printf( "-c <file> Path to config file.\n" "Data source:\n" "default Fetch latest update.\n" "-u <url> Fetch from specified URL.\n" "-f <file> Use specified file. (Must already be decompressed.)\n" "Actions:\n" "default Apply data to database.\n" "-t Report datestamp on download or file, do not apply to database.\n" "Options:\n" "-i Insecure. Circumvent certificate checks if necessary.\n" "-p Print activity as well as logging.\n" ); exit(1); } char zs[1024]; start_time = time(NULL); debug = *conf[conf_debug]; _log_init(debug?"/tmp/tscdb.log":"/var/log/garner/tscdb.log", (debug?1:(verbose?4:0))); _log(GENERAL, ""); _log(GENERAL, "%s %s", NAME, BUILD); // Enable core dumps struct rlimit limit; if(!getrlimit(RLIMIT_CORE, &limit)) { limit.rlim_cur = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &limit); } int i; for(i = 0; i < MATCHES; i++) { if(regcomp(&match[i], match_strings[i], REG_ICASE + REG_EXTENDED)) { sprintf(zs, "Failed to compile regex match %d", i); _log(MAJOR, zs); } } // Initialise database if(db_init(conf[conf_db_server], conf[conf_db_user], conf[conf_db_password], conf[conf_db_name])) exit(1); { word e; if((e=database_upgrade(cifdb))) { _log(CRITICAL, "Error %d in upgrade_database(). Aborting.", e); exit(1); } } run = 1; tiploc_ignored = false; // Zero the stats { word i; for(i = 0; i < MAXStats; i++) { stats[i] = 0; } } if(fetch_file()) { if(opt_url || opt_filename) { _log(GENERAL, "Failed to find data."); exit(1); } { char report[256]; _log(GENERAL, "Failed to fetch file."); sprintf(report, "Failed to collect timetable update after %lld attempts.", stats[Fetches]); email_alert(NAME, BUILD, "Timetable Update Failure Report", report); } exit(1); } char in_q = 0; char b_depth = 0; size_t ibuf = 0; size_t iobj = 0; size_t buf_end; // Determine applicable update { MYSQL_RES * result0; MYSQL_ROW row0; last_update_id[0] = '\0'; if(!db_query("SELECT MAX(id) FROM updates_processed")) { result0 = db_store_result(); if((row0 = mysql_fetch_row(result0))) { strcpy(last_update_id, row0[0]); } mysql_free_result(result0); } } if(last_update_id[0] == '\0') { _log(CRITICAL, "Failed to determine last update id from database."); exit(1); } if(test_mode) { } else { char c, pc; pc = 0; // Run through the file splitting off each JSON object and passing it on for processing. // DB may have dropped out due to long delay (void) db_connect(); if(db_start_transaction()) _log(CRITICAL, "Failed to initiate database transaction."); while((buf_end = fread(buffer, 1, MAX_BUF, fp_result)) && run && !db_errored) { for(ibuf = 0; ibuf < buf_end && run && !db_errored; ibuf++) { c = buffer[ibuf]; if(c != '\r' && c != '\n') { obj[iobj++] = c; if(iobj >= MAX_OBJ) { _log(CRITICAL, "Object buffer overflow!"); exit(1); } if(c == '"' && pc != '\\') in_q = ! in_q; if(!in_q && c == '{') b_depth++; if(!in_q && c == '}' && b_depth-- && !b_depth) { obj[iobj] = '\0'; process_object(obj); iobj = 0; } } pc = c; } } fclose(fp_result); if(db_errored) { _log(CRITICAL, "Update rolled back due to database error."); (void) db_rollback_transaction(); } else { _log(GENERAL, "Committing database updates..."); if(db_commit_transaction()) { _log(CRITICAL, "Database commit failed."); } else { _log(GENERAL, "Committed."); } } } #define REPORT_SIZE 16384 char report[REPORT_SIZE]; report[0] = '\0'; _log(GENERAL, ""); _log(GENERAL, "End of run:"); if(used_insecure) { strcat(report, "*** Warning: Insecure download used.\n"); _log(GENERAL, "*** Warning: Insecure download used."); } sprintf(zs, " Elapsed time: %ld minutes", (time(NULL) - start_time + 30) / 60); _log(GENERAL, zs); strcat(report, zs); strcat(report, "\n"); if(test_mode) { sprintf(zs, "Test mode. No database changes made."); _log(GENERAL, zs); strcat(report, zs); strcat(report, "\n"); exit(0); } for(i=0; i<MAXStats; i++) { sprintf(zs, "%25s: %s", stats_category[i], commas_q(stats[i])); if(i == DBError && stats[i]) strcat(zs, " ****************"); _log(GENERAL, zs); strcat(report, zs); strcat(report, "\n"); } db_disconnect(); email_alert(NAME, BUILD, "Timetable Update Report", report); exit(0); }
void ModelObject::read_obj(const char * filename) { int vert_id = 1; std::string temp; std::string obj_line; std::ifstream obj_file (filename); if (obj_file.is_open()) { while (getline(obj_file, obj_line)) { if (obj_line[0] == 'v') { std::istringstream vert_string (obj_line); coord * new_coord = new coord; new_coord->id = vert_id; for (int i = 0; i < 4; i++) { if (getline(vert_string, temp, ' ')) { if (i == 1) { new_coord->x = (float)atof(temp.c_str()); } else if (i == 2) { new_coord->y = (float)atof(temp.c_str()); } else if (i == 3) { new_coord->z = (float)atof(temp.c_str()); } } } object->vertices.push_back(new_coord); object->vert_count++; vert_id++; } else if (obj_line[0] == 'f') { object->face_count++; std::istringstream face_string (obj_line); face * new_face = new face; int coord_id; getline(face_string, temp, ' '); while (getline(face_string, temp, ' ')) { coord_id = (int)atoi(temp.c_str()); new_face->coords.push_back(object->vertices[coord_id - 1]); } object->faces.push_back(new_face); } else if (obj_line[0] == 'o' && object->obj_name == 0) { std::string name_string (obj_line); if (name_string.length() > 2) { object->obj_name = new char[name_string.length() - 1]; for (int i = 2; i < name_string.length(); i++) object->obj_name[i - 2] = name_string[i]; } } } obj_file.close(); process_object(); } }
/* * process_class - process a class * HEAP_CACHE_ATTRINFO structure * return: error status * class_oid(in): the class OID * hfid(in): the class HFID * max_space_to_process(in): maximum space to process * instance_lock_timeout(in): the lock timeout for instances * space_to_process(in, out): space to process * last_processed_oid(in, out): last processed oid * total_objects(in, out): count the processed class objects * failed_objects(in, out): count the failed class objects * modified_objects(in, out): count the modified class objects * big_objects(in, out): count the big class objects */ static int process_class (THREAD_ENTRY * thread_p, OID * class_oid, HFID * hfid, int max_space_to_process, int *instance_lock_timeout, int *space_to_process, OID * last_processed_oid, int *total_objects, int *failed_objects, int *modified_objects, int *big_objects) { int nobjects, nfetched, i, j; OID last_oid, prev_oid; LOCK null_lock = NULL_LOCK; LOCK oid_lock = X_LOCK; LC_COPYAREA *fetch_area = NULL; /* Area where objects are received */ struct lc_copyarea_manyobjs *mobjs; /* Describe multiple objects in area */ struct lc_copyarea_oneobj *obj; /* Describe on object in area */ RECDES recdes; HEAP_CACHE_ATTRINFO attr_info; HEAP_SCANCACHE upd_scancache; int ret = NO_ERROR, object_processed; int nfailed_instances = 0; if (class_oid == NULL || hfid == NULL || space_to_process == NULL || *space_to_process <= 0 || *space_to_process > max_space_to_process || last_processed_oid == NULL || total_objects == NULL || failed_objects == NULL || modified_objects == NULL || big_objects == NULL || *total_objects < 0 || *failed_objects < 0) { return ER_FAILED; } nobjects = 0; nfetched = -1; ret = heap_scancache_start_modify (thread_p, &upd_scancache, hfid, class_oid, SINGLE_ROW_UPDATE); if (ret != NO_ERROR) { return ER_FAILED; } ret = heap_attrinfo_start (thread_p, class_oid, -1, NULL, &attr_info); if (ret != NO_ERROR) { heap_scancache_end_modify (thread_p, &upd_scancache); return ER_FAILED; } COPY_OID (&last_oid, last_processed_oid); COPY_OID (&prev_oid, last_processed_oid); while (nobjects != nfetched) { ret = xlocator_lock_and_fetch_all (thread_p, hfid, &oid_lock, instance_lock_timeout, class_oid, &null_lock, &nobjects, &nfetched, &nfailed_instances, &last_oid, &fetch_area); if (ret == NO_ERROR) { (*total_objects) += nfailed_instances; (*failed_objects) += nfailed_instances; if (fetch_area != NULL) { mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (fetch_area); obj = LC_START_ONEOBJ_PTR_IN_COPYAREA (mobjs); for (i = 0; i < mobjs->num_objs; i++) { if (obj->length > *space_to_process) { if (*space_to_process == max_space_to_process) { (*total_objects)++; (*big_objects)++; lock_unlock_object (thread_p, &obj->oid, class_oid, oid_lock, true); } else { *space_to_process = 0; COPY_OID (last_processed_oid, &prev_oid); for (j = i; j < mobjs->num_objs; j++) { lock_unlock_object (thread_p, &obj->oid, class_oid, oid_lock, true); obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj); } if (fetch_area) { locator_free_copy_area (fetch_area); } goto end; } } else { *space_to_process -= obj->length; (*total_objects)++; LC_RECDES_TO_GET_ONEOBJ (fetch_area, obj, &recdes); if (desc_disk_to_attr_info (thread_p, &obj->oid, &recdes, &attr_info) == NO_ERROR) { object_processed = process_object (thread_p, &upd_scancache, &attr_info, &obj->oid); if (object_processed != 1) { lock_unlock_object (thread_p, &obj->oid, class_oid, oid_lock, true); if (object_processed == -1) { (*failed_objects)++; } } else { (*modified_objects)++; } } else { (*failed_objects)++; } } COPY_OID (&prev_oid, &obj->oid); obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj); } if (fetch_area) { locator_free_copy_area (fetch_area); } } else { /* No more objects */ break; } } else { ret = ER_FAILED; break; } } COPY_OID (last_processed_oid, &last_oid); end: heap_attrinfo_end (thread_p, &attr_info); heap_scancache_end_modify (thread_p, &upd_scancache); return ret; }
static void process_workitems(MVMThreadContext *tc, MVMHeapSnapshotState *ss) { while (ss->num_workitems > 0) { MVMHeapSnapshotWorkItem item = pop_workitem(tc, ss); /* We take our own working copy of the collectable info, since the * collectables array can grow and be reallocated. */ MVMHeapSnapshotCollectable col; set_ref_from(tc, ss, item.col_idx); col = ss->hs->collectables[item.col_idx]; col.kind = item.kind; switch (item.kind) { case MVM_SNAPSHOT_COL_KIND_OBJECT: case MVM_SNAPSHOT_COL_KIND_TYPE_OBJECT: process_object(tc, ss, &col, (MVMObject *)item.target); break; case MVM_SNAPSHOT_COL_KIND_STABLE: { MVMuint16 i; MVMSTable *st = (MVMSTable *)item.target; process_collectable(tc, ss, &col, (MVMCollectable *)st); set_type_index(tc, ss, &col, st); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->method_cache, "Method cache"); for (i = 0; i < st->type_check_cache_length; i++) MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->type_check_cache[i], "Type cache entry"); if (st->container_spec && st->container_spec->gc_mark_data) { st->container_spec->gc_mark_data(tc, st, ss->gcwl); process_gc_worklist(tc, ss, "Container spec data item"); } if (st->boolification_spec) MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->boolification_spec->method, "Boolification method"); if (st->invocation_spec) { MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->class_handle, "Invocation spec class handle"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->attr_name, "Invocation spec attribute name"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->invocation_handler, "Invocation spec invocation handler"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->md_class_handle, "Invocation spec class handle (multi)"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->md_cache_attr_name, "Invocation spec cache attribute name (multi)"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->invocation_spec->md_valid_attr_name, "Invocation spec valid attribute name (multi)"); } MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->WHO, "WHO"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->WHAT, "WHAT"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->HOW, "HOW"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->HOW_sc, "HOW serialization context"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->method_cache_sc, "Method cache serialization context"); if (st->mode_flags & MVM_PARAMETRIC_TYPE) { MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->paramet.ric.parameterizer, "Parametric type parameterizer"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->paramet.ric.lookup, "Parametric type intern table"); } else if (st->mode_flags & MVM_PARAMETERIZED_TYPE) { MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->paramet.erized.parametric_type, "Parameterized type's parametric type"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)st->paramet.erized.parameters, "Parameterized type's parameters"); } if (st->REPR->gc_mark_repr_data) { st->REPR->gc_mark_repr_data(tc, st, ss->gcwl); process_gc_worklist(tc, ss, "REPR data item"); } break; } case MVM_SNAPSHOT_COL_KIND_FRAME: { MVMFrame *frame = (MVMFrame *)item.target; col.collectable_size = sizeof(MVMFrame); set_static_frame_index(tc, ss, &col, frame->static_info); if (frame->caller && !MVM_FRAME_IS_ON_CALLSTACK(tc, frame)) add_reference_const_cstr(tc, ss, "Caller", get_frame_idx(tc, ss, frame->caller)); if (frame->outer) add_reference_const_cstr(tc, ss, "Outer", get_frame_idx(tc, ss, frame->outer)); MVM_gc_root_add_frame_registers_to_worklist(tc, ss->gcwl, frame); process_gc_worklist(tc, ss, "Register"); if (frame->work) col.unmanaged_size += frame->allocd_work; if (frame->env) { MVMuint16 i, count; MVMuint16 *type_map; MVMuint16 name_count = frame->static_info->body.num_lexicals; MVMLexicalRegistry **names = frame->static_info->body.lexical_names_list; if (frame->spesh_cand && frame->spesh_log_idx == -1 && frame->spesh_cand->lexical_types) { type_map = frame->spesh_cand->lexical_types; count = frame->spesh_cand->num_lexicals; } else { type_map = frame->static_info->body.lexical_types; count = frame->static_info->body.num_lexicals; } for (i = 0; i < count; i++) { if (type_map[i] == MVM_reg_str || type_map[i] == MVM_reg_obj) { if (i < name_count) MVM_profile_heap_add_collectable_rel_vm_str(tc, ss, (MVMCollectable *)frame->env[i].o, names[i]->key); else MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)frame->env[i].o, "Lexical (inlined)"); } } col.unmanaged_size += frame->allocd_env; } MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)frame->code_ref, "Code reference"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)frame->static_info, "Static frame"); MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)frame->dynlex_cache_name, "Dynamic lexical cache name"); if (frame->special_return_data && frame->mark_special_return_data) { frame->mark_special_return_data(tc, frame, ss->gcwl); process_gc_worklist(tc, ss, "Special return data"); } if (frame->continuation_tags) { MVMContinuationTag *tag = frame->continuation_tags; while (tag) { MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, (MVMCollectable *)tag->tag, "Continuation tag"); col.unmanaged_size += sizeof(MVMContinuationTag); tag = tag->next; } } break; } case MVM_SNAPSHOT_COL_KIND_PERM_ROOTS: MVM_gc_root_add_permanents_to_worklist(tc, NULL, ss); break; case MVM_SNAPSHOT_COL_KIND_INSTANCE_ROOTS: MVM_gc_root_add_instance_roots_to_worklist(tc, NULL, ss); break; case MVM_SNAPSHOT_COL_KIND_CSTACK_ROOTS: MVM_gc_root_add_temps_to_worklist((MVMThreadContext *)item.target, NULL, ss); break; case MVM_SNAPSHOT_COL_KIND_THREAD_ROOTS: { MVMThreadContext *thread_tc = (MVMThreadContext *)item.target; MVM_gc_root_add_tc_roots_to_worklist(thread_tc, NULL, ss); if (thread_tc->cur_frame && !MVM_FRAME_IS_ON_CALLSTACK(thread_tc, tc->cur_frame)) add_reference_const_cstr(tc, ss, "Current frame", get_frame_idx(tc, ss, thread_tc->cur_frame)); break; } case MVM_SNAPSHOT_COL_KIND_ROOT: { MVMThread *cur_thread; add_reference_const_cstr(tc, ss, "Permanent Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_PERM_ROOTS, NULL)); add_reference_const_cstr(tc, ss, "VM Instance Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_INSTANCE_ROOTS, NULL)); cur_thread = tc->instance->threads; while (cur_thread) { if (cur_thread->body.tc) { add_reference_const_cstr(tc, ss, "C Stack Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_CSTACK_ROOTS, cur_thread->body.tc)); add_reference_const_cstr(tc, ss, "Thread Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_THREAD_ROOTS, cur_thread->body.tc)); add_reference_const_cstr(tc, ss, "Inter-generational Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_INTERGEN_ROOTS, cur_thread->body.tc)); add_reference_const_cstr(tc, ss, "Thread Call Stack Roots", push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_CALLSTACK_ROOTS, cur_thread->body.tc)); } cur_thread = cur_thread->body.next; } break; } case MVM_SNAPSHOT_COL_KIND_INTERGEN_ROOTS: { MVMThreadContext *thread_tc = (MVMThreadContext *)item.target; MVM_gc_root_add_gen2s_to_snapshot(thread_tc, ss); break; } case MVM_SNAPSHOT_COL_KIND_CALLSTACK_ROOTS: { MVMThreadContext *thread_tc = (MVMThreadContext *)item.target; if (thread_tc->cur_frame && MVM_FRAME_IS_ON_CALLSTACK(tc, thread_tc->cur_frame)) { MVMFrame *cur_frame = thread_tc->cur_frame; MVMint32 idx = 0; while (cur_frame && MVM_FRAME_IS_ON_CALLSTACK(tc, cur_frame)) { add_reference_idx(tc, ss, idx, push_workitem(tc, ss, MVM_SNAPSHOT_COL_KIND_FRAME, (MVMCollectable *)cur_frame)); idx++; cur_frame = cur_frame->caller; } } break; } default: MVM_panic(1, "Unknown heap snapshot worklist item kind %d", item.kind); } /* Store updated collectable info into array. Note that num_refs was * updated "at a distance". */ col.num_refs = ss->hs->collectables[item.col_idx].num_refs; ss->hs->collectables[item.col_idx] = col; } }
/* * Get the linkmap from the dynlinker. Try to load kernel modules * from all objects in the linkmap. */ void rumpuser_dl_bootstrap(rump_modinit_fn domodinit, rump_symload_fn symload, rump_compload_fn compload) { struct link_map *map, *origmap, *mainmap; void *mainhandle; int error; mainhandle = dlopen(NULL, RTLD_NOW); /* Will be null if statically linked so just return */ if (mainhandle == NULL) return; if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) { fprintf(stderr, "warning: rumpuser module bootstrap " "failed: %s\n", dlerror()); return; } origmap = mainmap; /* * Use a heuristic to determine if we are static linked. * A dynamically linked binary should always have at least * two objects: itself and ld.so. * * In a statically linked binary with glibc the linkmap * contains some "info" that leads to a segfault. Since we * can't really do anything useful in here without ld.so, just * simply bail and let the symbol references in librump do the * right things. */ if (origmap->l_next == NULL && origmap->l_prev == NULL) { dlclose(mainhandle); return; } /* * Process last->first because that's the most probable * order for dependencies */ for (; origmap->l_next; origmap = origmap->l_next) continue; /* * Build symbol table to hand to the rump kernel. Do this by * iterating over all rump libraries and collecting symbol * addresses and relocation info. */ error = 0; for (map = origmap; map && !error; map = map->l_prev) { if (strstr(map->l_name, "librump") != NULL || map == mainmap) error = getsymbols(map, map == mainmap); } if (error == 0) { void *trimmedsym, *trimmedstr; /* * Allocate optimum-sized memory for storing tables * and feed to kernel. If memory allocation fails, * just give the ones with extra context (although * I'm pretty sure we'll die moments later due to * memory running out). */ if ((trimmedsym = malloc(symtaboff)) != NULL) { memcpy(trimmedsym, symtab, symtaboff); } else { trimmedsym = symtab; symtab = NULL; } if ((trimmedstr = malloc(strtaboff)) != NULL) { memcpy(trimmedstr, strtab, strtaboff); } else { trimmedstr = strtab; strtab = NULL; } symload(trimmedsym, symtaboff, trimmedstr, strtaboff); } free(symtab); free(strtab); /* * Next, load modules and components. * * Simply loop through all objects, ones unrelated to rump kernels * will not contain link_set_rump_components (well, not including * "sabotage", but that needs to be solved at another level anyway). */ for (map = origmap; map; map = map->l_prev) { void *handle; if (map == mainmap) { handle = mainhandle; } else { handle = dlopen(map->l_name, RTLD_LAZY); if (handle == NULL) continue; } process_object(handle, domodinit, compload); if (map != mainmap) dlclose(handle); } }