obs_source_t obs_source_create(enum obs_source_type type, const char *id, const char *name, const char *settings) { struct obs_source *source; const struct source_info *info = get_source_info(type, id); if (!info) { blog(LOG_WARNING, "Source '%s' not found", id); return NULL; } source = bmalloc(sizeof(struct obs_source)); memset(source, 0, sizeof(struct obs_source)); if (!obs_source_init_handlers(source)) goto fail; source->name = bstrdup(name); source->type = type; source->data = info->create(settings, source); if (!source->data) goto fail; if (!obs_source_init(source, settings, info)) goto fail; obs_source_dosignal(source, "source-create"); return source; fail: blog(LOG_ERROR, "obs_source_create failed"); obs_source_destroy(source); return NULL; }
obs_source_t obs_source_create(enum obs_source_type type, const char *id, const char *name, obs_data_t settings) { struct obs_source *source; const struct obs_source_info *info = get_source_info(type, id); if (!info) { blog(LOG_ERROR, "Source '%s' not found", id); return NULL; } source = bzalloc(sizeof(struct obs_source)); if (!obs_source_init_context(source, settings, name)) goto fail; if (info->defaults) info->defaults(source->context.settings); source->context.data = info->create(source->context.settings, source); if (!source->context.data) goto fail; if (!obs_source_init(source, info)) goto fail; obs_source_dosignal(source, "source_create", NULL); return source; fail: blog(LOG_ERROR, "obs_source_create failed"); obs_source_destroy(source); return NULL; }
obs_properties_t obs_source_properties(enum obs_source_type type, const char *id, const char *locale) { const struct source_info *info = get_source_info(type, id); if (info && info->properties) return info->properties(locale); return NULL; }
obs_properties_t obs_get_source_properties(enum obs_source_type type, const char *id, const char *locale) { const struct obs_source_info *info = get_source_info(type, id); if (info && info->properties) { obs_data_t defaults = get_defaults(info); obs_properties_t properties; properties = info->properties(locale); obs_properties_apply_settings(properties, defaults); obs_data_release(defaults); return properties; } return NULL; }
void CVmBifT3::get_stack_trace(VMG_ uint argc) { int single_level = 0; int level; vm_val_t *fp; vm_val_t lst_val; CVmObjList *lst; const uchar *entry_addr; ulong method_ofs; vm_val_t stack_info_cls; int want_named_args = FALSE; int want_locals = FALSE; int want_frefs = FALSE; int flags = 0; const vm_rcdesc *rc; /* check arguments */ check_argc_range(vmg_ argc, 0, 2); /* get the imported stack information class */ stack_info_cls.set_obj(G_predef->stack_info_cls); if (stack_info_cls.val.obj == VM_INVALID_OBJ) { /* * there's no stack information class - we can't return any * meaningful information, so just return nil */ retval_nil(vmg0_); return; } /* * look up T3StackInfo.construct() to determine how many arguments it * wants */ { int min_args, opt_args, varargs; if (vm_objp(vmg_ stack_info_cls.val.obj)->get_prop_interface( vmg_ stack_info_cls.val.obj, G_predef->obj_construct, min_args, opt_args, varargs)) { /* check to see how many extra arguments they want */ want_named_args = (min_args + opt_args >= 7 || varargs); want_locals = (min_args + opt_args >= 8 || varargs); want_frefs = (min_args + opt_args >= 9 || varargs); } } /* check to see if we're fetching a single level or the full trace */ if (argc >= 1) { /* * Get the single level, and adjust to a 0 base. If the level is * nil, we're still getting all levels. */ if (G_stk->get(0)->typ == VM_NIL) { /* it's nil - get all levels */ G_stk->discard(); } else { /* get the level number */ single_level = pop_int_val(vmg0_); /* make sure it's in range */ if (single_level <= 0) err_throw(VMERR_BAD_VAL_BIF); /* we won't need a return list */ lst_val.set_obj_or_nil(VM_INVALID_OBJ); lst = 0; } } /* get the flags argument, if present */ if (argc >= 2) flags = pop_int_val(vmg0_); /* if we're not doing a single level, we need a list for the result */ if (!single_level) { /* * We're returning a full list, so we need to allocate the list for * the return value. First, count stack levels to see how big a * list we'll need. */ fp = G_interpreter->get_frame_ptr(); entry_addr = G_interpreter->get_entry_ptr(); method_ofs = G_interpreter->get_method_ofs(); for (level = 0 ; fp != 0 ; fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp), ++level) { /* add an extra level for each system call */ if (method_ofs == 0 && entry_addr != 0) ++level; /* get the return address */ entry_addr = G_interpreter->get_enclosing_entry_ptr_from_frame(vmg_ fp); method_ofs = G_interpreter->get_return_ofs_from_frame(vmg_ fp); } /* create the list */ lst_val.set_obj(CVmObjList::create(vmg_ FALSE, level)); lst = (CVmObjList *)vm_objp(vmg_ lst_val.val.obj); /* * we create other objects while building this list, so the gc * could run - clear the list to ensure it contains valid data */ lst->cons_clear(); /* protect the list from garbage collection while we work */ G_stk->push(&lst_val); /* flag that we're doing the whole stack */ single_level = -1; } else { /* adjust the level to a 0-based index */ single_level -= 1; } /* set up at the current function */ fp = G_interpreter->get_frame_ptr(); entry_addr = G_interpreter->get_entry_ptr(); method_ofs = G_interpreter->get_method_ofs(); rc = 0; /* traverse the frames */ for (level = 0 ; fp != 0 ; ++level) { int fr_argc; int i; vm_obj_id_t def_obj; vm_val_t info_self; vm_val_t info_func; vm_val_t info_obj; vm_val_t info_prop; vm_val_t info_args; vm_val_t info_locals; vm_val_t info_srcloc; vm_val_t info_frameref; CVmObjList *arglst; vm_val_t ele; CVmFuncPtr func_ptr; int gc_cnt = 0; int info_argc = 0; /* if we're looking for a single level, and this isn't it, skip it */ if (single_level >= 0 && level != single_level) goto done_with_level; /* * start with the information values to nil - we'll set the * appropriate ones when we find out what we have */ info_func.set_nil(); info_obj.set_nil(); info_prop.set_nil(); info_self.set_nil(); info_locals.set_nil(); info_frameref.set_nil(); /* get the number of arguments to the function in this frame */ fr_argc = G_interpreter->get_argc_from_frame(vmg_ fp); /* set up a function pointer for the method's entry address */ func_ptr.set(entry_addr); /* get the current frame's defining object */ def_obj = G_interpreter->get_defining_obj_from_frame(vmg_ fp); /* check for special method offsets */ switch (method_ofs) { case VMRUN_RET_OP: /* the real return address is one past the last argument */ method_ofs = G_interpreter->get_param_from_frame(vmg_ fp, argc) ->val.intval; break; case VMRUN_RET_OP_ASILCL: /* the real return address is two past the last argument */ method_ofs = G_interpreter->get_param_from_frame(vmg_ fp, argc+1) ->val.intval; break; } /* determine whether it's an object.prop or a function call */ if (method_ofs == 0) { /* * A zero method offset indicates a recursive VM invocation * from a native function. Presume we have no information on * the caller. */ info_self.set_nil(); fr_argc = 0; /* check for a native caller context */ if (rc != 0) { /* check which kind of native caller we have */ if (rc->bifptr.typ != VM_NIL) { /* we have a built-in function at this level */ info_func = rc->bifptr; } else if (rc->self.typ != VM_NIL) { /* it's an intrinsic class method - get the 'self' */ info_obj = info_self = rc->self; /* get the metaclass */ CVmMetaclass *mc; switch (info_obj.typ) { case VM_OBJ: /* get the metaclass from the object */ mc = vm_objp(vmg_ info_obj.val.obj) ->get_metaclass_reg(); break; case VM_LIST: /* list constant - use the List metaclass */ mc = CVmObjList::metaclass_reg_; break; case VM_SSTRING: /* string constant - use the String metaclass */ mc = CVmObjString::metaclass_reg_; break; default: /* other types don't have metaclasses */ mc = 0; break; } /* get the registration table entry */ vm_meta_entry_t *me = mc == 0 ? 0 : G_meta_table->get_entry_from_reg(mc->get_reg_idx()); /* get the metaclass and property from the entry */ if (me != 0) { /* set 'obj' to the IntrinsicClass object */ info_obj.set_obj(me->class_obj_); /* get the property ID */ info_prop.set_propid(me->xlat_func(rc->method_idx)); } } } } else if (def_obj == VM_INVALID_OBJ) { /* there's no defining object, so this is a function call */ func_ptr.get_fnptr(vmg_ &info_func); } else { /* it's an object.prop invocation */ info_obj.set_obj(def_obj); // $$$ walk up to base modified obj? info_prop.set_propid( G_interpreter->get_target_prop_from_frame(vmg_ fp)); /* get the 'self' in this frame */ info_self.set_obj(G_interpreter->get_self_from_frame(vmg_ fp)); } /* * build the argument list and source location, except for system * routines */ if (method_ofs != 0 || rc != 0) { /* allocate a list object to store the argument list */ int ac = (rc != 0 ? rc->argc : fr_argc); info_args.set_obj(CVmObjList::create(vmg_ FALSE, ac)); arglst = (CVmObjList *)vm_objp(vmg_ info_args.val.obj); /* push the argument list for gc protection */ G_stk->push(&info_args); ++gc_cnt; /* build the argument list */ for (i = 0 ; i < ac ; ++i) { /* add this element to the argument list */ const vm_val_t *v = (rc != 0 ? rc->argp - i : G_interpreter->get_param_from_frame(vmg_ fp, i)); arglst->cons_set_element(i, v); } /* get the source location */ get_source_info(vmg_ entry_addr, method_ofs, &info_srcloc); /* * if they want locals, and this isn't a recursive native * caller, retrieve them */ if (rc == 0 && (((flags & T3_GST_LOCALS) != 0 && want_locals) || ((flags & T3_GST_FREFS) != 0 && want_frefs))) { /* get the locals */ get_stack_locals(vmg_ fp, entry_addr, method_ofs, (flags & T3_GST_LOCALS) != 0 && want_locals ? &info_locals : 0, (flags & T3_GST_FREFS) != 0 && want_frefs ? &info_frameref : 0); /* * that leaves the LookupTable and StackFrameDesc on the * stack, so note that we need to discard the stack level * when we're done with it */ if (info_locals.typ == VM_OBJ) ++gc_cnt; if (info_frameref.typ == VM_OBJ) ++gc_cnt; } } else { /* * it's a system routine - no argument information is * available, so return nil rather than an empty list to to * indicate the absence */ info_args.set_nil(); /* there's obviously no source location for system code */ info_srcloc.set_nil(); } /* * We have all of the information on this level now, so create the * information object for the level. This is an object of the * exported stack-info class, which is a TadsObject type. */ /* start with the original complement of arguments */ info_argc = 7; /* * if we have a modern T3StackInfo object, push the locals, * named argument elements, and frame reference object */ if (want_frefs) { G_stk->push(&info_frameref); ++info_argc; } if (want_named_args) { /* * the constructor has a slot for named arguments - push either * a table or nil, depending... */ vm_val_t *argp; const uchar *t = 0; /* if the flags request locals, retrieve the named arguments */ if ((flags & T3_GST_LOCALS) != 0) t = CVmRun::get_named_args_from_frame(vmg_ fp, &argp); /* * if we do in fact have named arguments, build a lookup table * copy and push it; otherwise just push nil */ if (t != 0) { /* get the number of table entries */ int n = osrp2(t); t += 2; /* create a lookup table for the arguments */ G_stk->push()->set_obj(CVmObjLookupTable::create( vmg_ FALSE, n <= 8 ? 8 : n <= 32 ? 32 : 64, n)); CVmObjLookupTable *lt = (CVmObjLookupTable *)vm_objp( vmg_ G_stk->get(0)->val.obj); /* * Populate the lookup table with the named arguments. The * compiler builds the table in the order pushed, which is * right to left. Lookup tables preserve the order in * which elements are added, and reflect this order in key * lists, so to that extent the order of building the * lookup table matters. For readability of the generated * list, in case it's presented to the user, build the * table in left-to-right order, which is the reverse of * the table order in the bytecode table. */ argp += n - 1; for (int i = (n-1)*2 ; i >= 0 ; i -= 2, --argp) { /* get the name pointer and length from the index */ uint ofs = osrp2(t + i), nxtofs = osrp2(t + i + 2); const char *name = (const char *)t + ofs; size_t len = nxtofs - ofs; /* create a string from the name */ vm_val_t str; str.set_obj(CVmObjString::create(vmg_ FALSE, name, len)); /* add it to the table */ lt->add_entry(vmg_ &str, argp); } } else { /* there are no named arguments - push nil */ G_stk->push()->set_nil(); } /* count the argument */ ++info_argc; } if (want_locals) { G_stk->push(&info_locals); ++info_argc; } /* push the rest of the arguments */ G_stk->push(&info_srcloc); G_stk->push(&info_args); G_stk->push(&info_self); G_stk->push(&info_prop); G_stk->push(&info_obj); G_stk->push(&info_func); G_stk->push(&stack_info_cls); ele.set_obj(CVmObjTads::create_from_stack(vmg_ 0, info_argc)); /* discard the gc protection items */ G_stk->discard(gc_cnt); /* * if we're fetching a single level, this is it - return the new * stack info object and we're done */ if (single_level >= 0) { /* return the single level object */ retval_obj(vmg_ ele.val.obj); /* we're done */ return; } /* add the new element to our list */ lst->cons_set_element(level, &ele); done_with_level: /* * If this is a system call level, and we're not in debug mode, * this recursive frame contains the entry address for the caller, * but not the calling byte-code address. Stay on the current * level in this case. */ if (method_ofs == 0 && entry_addr != 0) { /* * This is a recursive caller, and we have a valid entry * address for the prior frame. Stay in the current frame, and * retrieve the actual return address from the calling frame. */ if (rc != 0) { /* get the actual return address from the recursive context */ method_ofs = rc->return_addr - entry_addr; /* * we're now in the bytecode part of the frame, so forget * the recursive context */ rc = 0; } else { /* no recursive context - use a fake return address */ method_ofs = G_interpreter->get_funchdr_size(); } } else { /* move up to the enclosing frame */ entry_addr = G_interpreter->get_enclosing_entry_ptr_from_frame(vmg_ fp); method_ofs = G_interpreter->get_return_ofs_from_frame(vmg_ fp); rc = G_interpreter->get_rcdesc_from_frame(vmg_ fp); fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp); } } /* return the list */ retval_obj(vmg_ lst_val.val.obj); /* discard our gc protection */ G_stk->discard(); }
/* * mono_debug_symfile_get_line_numbers_full: * * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile * structures, and SOURCE_FILES will contain indexes into this array. * The MonoDebugSourceFile structures are owned by this module. */ void mono_debug_symfile_get_line_numbers_full (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int *n_il_offsets, int **il_offsets, int **line_numbers, int **source_files) { // FIXME: Unify this with mono_debug_symfile_lookup_location MonoSymbolFile *symfile; const unsigned char *ptr; StatementMachine stm; uint32_t i; GPtrArray *il_offset_array, *line_number_array, *source_file_array; if (source_file_list) *source_file_list = NULL; if (n_il_offsets) *n_il_offsets = 0; if (source_files) *source_files = NULL; if (source_file) *source_file = NULL; if ((symfile = minfo->handle->symfile) == NULL) return; il_offset_array = g_ptr_array_new (); line_number_array = g_ptr_array_new (); source_file_array = g_ptr_array_new (); stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base); stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range); stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base); stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range; mono_debugger_lock (); ptr = symfile->raw_contents + minfo->lnt_offset; stm.symfile = symfile; stm.offset = stm.last_offset = 0; stm.last_file = 0; stm.last_line = 0; stm.first_file = 0; stm.file = 1; stm.line = 1; stm.is_hidden = FALSE; while (TRUE) { uint8_t opcode = *ptr++; if (opcode == 0) { uint8_t size = *ptr++; const unsigned char *end_ptr = ptr + size; opcode = *ptr++; if (opcode == DW_LNE_end_sequence) { if (il_offset_array->len == 0) /* Empty table */ break; add_line (&stm, il_offset_array, line_number_array, source_file_array); break; } else if (opcode == DW_LNE_MONO_negate_is_hidden) { stm.is_hidden = !stm.is_hidden; } else if ((opcode >= DW_LNE_MONO__extensions_start) && (opcode <= DW_LNE_MONO__extensions_end)) { ; // reserved for future extensions } else { g_warning ("Unknown extended opcode %x in LNT", opcode); } ptr = end_ptr; continue; } else if (opcode < stm.opcode_base) { switch (opcode) { case DW_LNS_copy: add_line (&stm, il_offset_array, line_number_array, source_file_array); break; case DW_LNS_advance_pc: stm.offset += read_leb128 (ptr, &ptr); break; case DW_LNS_advance_line: stm.line += read_leb128 (ptr, &ptr); break; case DW_LNS_set_file: stm.file = read_leb128 (ptr, &ptr); break; case DW_LNS_const_add_pc: stm.offset += stm.max_address_incr; break; default: g_warning ("Unknown standard opcode %x in LNT", opcode); g_assert_not_reached (); } } else { opcode -= stm.opcode_base; stm.offset += opcode / stm.line_range; stm.line += stm.line_base + (opcode % stm.line_range); add_line (&stm, il_offset_array, line_number_array, source_file_array); } } if (!stm.file && stm.first_file) stm.file = stm.first_file; if (stm.file && source_file) { int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) + (stm.file - 1) * sizeof (MonoSymbolFileSourceEntry); MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (stm.symfile->raw_contents + offset); if (source_file) *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)), NULL); } if (source_file_list) { int file, last_file = 0; *source_file_list = g_ptr_array_new (); if (source_files) *source_files = g_malloc (il_offset_array->len * sizeof (int)); for (i = 0; i < il_offset_array->len; ++i) { file = GPOINTER_TO_UINT (g_ptr_array_index (source_file_array, i)); if (file && file != last_file) { MonoDebugSourceInfo *info = get_source_info (symfile, file); g_ptr_array_add (*source_file_list, info); } last_file = file; if (source_files) (*source_files) [i] = (*source_file_list)->len - 1; } if ((*source_file_list)->len == 0 && stm.file) { MonoDebugSourceInfo *info = get_source_info (symfile, stm.file); g_ptr_array_add (*source_file_list, info); } } if (n_il_offsets) *n_il_offsets = il_offset_array->len; if (il_offsets && line_numbers) { *il_offsets = g_malloc (il_offset_array->len * sizeof (int)); *line_numbers = g_malloc (il_offset_array->len * sizeof (int)); for (i = 0; i < il_offset_array->len; ++i) { (*il_offsets) [i] = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array, i)); (*line_numbers) [i] = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i)); } } g_ptr_array_free (il_offset_array, TRUE); g_ptr_array_free (line_number_array, TRUE); mono_debugger_unlock (); return; }
void obs_register_source_s(const struct obs_source_info *info, size_t size) { struct obs_source_info data = {0}; struct darray *array = NULL; if (info->type == OBS_SOURCE_TYPE_INPUT) { array = &obs->input_types.da; } else if (info->type == OBS_SOURCE_TYPE_FILTER) { array = &obs->filter_types.da; } else if (info->type == OBS_SOURCE_TYPE_TRANSITION) { array = &obs->transition_types.da; } else if (info->type != OBS_SOURCE_TYPE_SCENE) { source_warn("Tried to register unknown source type: %u", info->type); goto error; } if (get_source_info(info->id)) { source_warn("Source '%s' already exists! " "Duplicate library?", info->id); goto error; } memcpy(&data, info, size); /* mark audio-only filters as an async filter categorically */ if (data.type == OBS_SOURCE_TYPE_FILTER) { if ((data.output_flags & OBS_SOURCE_VIDEO) == 0) data.output_flags |= OBS_SOURCE_ASYNC; } if (data.type == OBS_SOURCE_TYPE_TRANSITION) { if (data.get_width) source_warn("get_width ignored registering " "transition '%s'", data.id); if (data.get_height) source_warn("get_height ignored registering " "transition '%s'", data.id); data.output_flags |= OBS_SOURCE_COMPOSITE | OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; } if ((data.output_flags & OBS_SOURCE_COMPOSITE) != 0) { if ((data.output_flags & OBS_SOURCE_AUDIO) != 0) { source_warn("Source '%s': Composite sources " "cannot be audio sources", info->id); goto error; } if ((data.output_flags & OBS_SOURCE_ASYNC) != 0) { source_warn("Source '%s': Composite sources " "cannot be async sources", info->id); goto error; } } #define CHECK_REQUIRED_VAL_(info, val, func) \ CHECK_REQUIRED_VAL(struct obs_source_info, info, val, func) CHECK_REQUIRED_VAL_(info, get_name, obs_register_source); CHECK_REQUIRED_VAL_(info, create, obs_register_source); CHECK_REQUIRED_VAL_(info, destroy, obs_register_source); if (info->type != OBS_SOURCE_TYPE_FILTER && info->type != OBS_SOURCE_TYPE_TRANSITION && (info->output_flags & OBS_SOURCE_VIDEO) != 0 && (info->output_flags & OBS_SOURCE_ASYNC) == 0) { CHECK_REQUIRED_VAL_(info, get_width, obs_register_source); CHECK_REQUIRED_VAL_(info, get_height, obs_register_source); } if ((data.output_flags & OBS_SOURCE_COMPOSITE) != 0) { CHECK_REQUIRED_VAL_(info, audio_render, obs_register_source); } #undef CHECK_REQUIRED_VAL_ if (size > sizeof(data)) { source_warn("Tried to register obs_source_info with size " "%llu which is more than libobs currently " "supports (%llu)", (long long unsigned)size, (long long unsigned)sizeof(data)); goto error; } if (array) darray_push_back(sizeof(struct obs_source_info), array, &data); da_push_back(obs->source_types, &data); return; error: HANDLE_ERROR(size, obs_source_info, info); }
/* * mono_debug_symfile_get_seq_points: * * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile * structures, and SOURCE_FILES will contain indexes into this array. * The MonoDebugSourceFile structures are owned by this module. */ void mono_debug_symfile_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points) { // FIXME: Unify this with mono_debug_symfile_lookup_location MonoSymbolFile *symfile; const unsigned char *ptr; StatementMachine stm; uint32_t i, j, n; LineNumberTableFlags flags; GPtrArray *il_offset_array, *line_number_array, *source_file_array, *hidden_array; gboolean has_column_info, has_end_info; MonoSymSeqPoint *sps; if (source_file_list) *source_file_list = NULL; if (seq_points) *seq_points = NULL; if (n_seq_points) *n_seq_points = 0; if (source_files) *source_files = NULL; if (source_file) *source_file = NULL; if ((symfile = minfo->handle->symfile) == NULL) return; flags = method_get_lnt_flags (minfo); has_column_info = (flags & LNT_FLAG_HAS_COLUMN_INFO) > 0; has_end_info = (flags & LNT_FLAG_HAS_END_INFO) > 0; il_offset_array = g_ptr_array_new (); line_number_array = g_ptr_array_new (); source_file_array = g_ptr_array_new (); hidden_array = g_ptr_array_new(); stm.line_base = read32 (&symfile->offset_table->_line_number_table_line_base); stm.line_range = read32 (&symfile->offset_table->_line_number_table_line_range); stm.opcode_base = (uint8_t) read32 (&symfile->offset_table->_line_number_table_opcode_base); stm.max_address_incr = (255 - stm.opcode_base) / stm.line_range; mono_debugger_lock (); ptr = symfile->raw_contents + minfo->lnt_offset; stm.symfile = symfile; stm.offset = stm.last_offset = 0; stm.last_file = 0; stm.last_line = 0; stm.first_file = 0; stm.file = 1; stm.line = 1; stm.is_hidden = FALSE; while (TRUE) { uint8_t opcode = *ptr++; if (opcode == 0) { uint8_t size = *ptr++; const unsigned char *end_ptr = ptr + size; opcode = *ptr++; if (opcode == DW_LNE_end_sequence) { if (il_offset_array->len == 0) /* Empty table */ break; break; } else if (opcode == DW_LNE_MONO_negate_is_hidden) { stm.is_hidden = !stm.is_hidden; } else if ((opcode >= DW_LNE_MONO__extensions_start) && (opcode <= DW_LNE_MONO__extensions_end)) { ; // reserved for future extensions } else { g_warning ("Unknown extended opcode %x in LNT", opcode); } ptr = end_ptr; continue; } else if (opcode < stm.opcode_base) { switch (opcode) { case DW_LNS_copy: add_line (&stm, il_offset_array, line_number_array, source_file_array, hidden_array); break; case DW_LNS_advance_pc: stm.offset += read_leb128 (ptr, &ptr); break; case DW_LNS_advance_line: stm.line += read_leb128 (ptr, &ptr); break; case DW_LNS_set_file: stm.file = read_leb128 (ptr, &ptr); break; case DW_LNS_const_add_pc: stm.offset += stm.max_address_incr; break; default: g_warning ("Unknown standard opcode %x in LNT", opcode); g_assert_not_reached (); } } else { opcode -= stm.opcode_base; stm.offset += opcode / stm.line_range; stm.line += stm.line_base + (opcode % stm.line_range); add_line (&stm, il_offset_array, line_number_array, source_file_array, hidden_array); } } if (!stm.file && stm.first_file) stm.file = stm.first_file; if (stm.file && source_file) { int offset = read32(&(stm.symfile->offset_table->_source_table_offset)) + (stm.file - 1) * sizeof (MonoSymbolFileSourceEntry); MonoSymbolFileSourceEntry *se = (MonoSymbolFileSourceEntry *) (stm.symfile->raw_contents + offset); if (source_file) *source_file = read_string (stm.symfile->raw_contents + read32(&(se->_data_offset)), NULL); } if (source_file_list) { int file, last_file = 0; *source_file_list = g_ptr_array_new (); if (source_files) *source_files = (int *)g_malloc (il_offset_array->len * sizeof (int)); for (i = 0; i < il_offset_array->len; ++i) { file = GPOINTER_TO_UINT (g_ptr_array_index (source_file_array, i)); if (file && file != last_file) { MonoDebugSourceInfo *info = get_source_info (symfile, file); g_ptr_array_add (*source_file_list, info); } last_file = file; if (source_files) (*source_files) [i] = (*source_file_list)->len - 1; } if ((*source_file_list)->len == 0 && stm.file) { MonoDebugSourceInfo *info = get_source_info (symfile, stm.file); g_ptr_array_add (*source_file_list, info); } } if (n_seq_points) { g_assert (seq_points); n = il_offset_array->len; for (i = 0; i < il_offset_array->len; i++) { if (GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) { n --; } } *n_seq_points = n; *seq_points = sps = g_new0 (MonoSymSeqPoint, n); j = 0; for (i = 0; i < il_offset_array->len; ++i) { MonoSymSeqPoint *sp = &(sps [j]); if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) { sp->il_offset = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array, i)); sp->line = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i)); sp->column = -1; sp->end_line = -1; sp->end_column = -1; j ++; } } if (has_column_info) { j = 0; for (i = 0; i < il_offset_array->len; ++i) { MonoSymSeqPoint *sp = &(sps [j]); int column = read_leb128 (ptr, &ptr); if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) { sp->column = column; j++; } } } if (has_end_info) { j = 0; for (i = 0; i < il_offset_array->len; ++i) { MonoSymSeqPoint *sp = &(sps [j]); int end_row, end_column = -1; end_row = read_leb128 (ptr, &ptr); if (end_row != 0xffffff) { end_row += GPOINTER_TO_UINT (g_ptr_array_index (line_number_array, i)); end_column = read_leb128 (ptr, &ptr); if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array, i))) { sp->end_line = end_row; sp->end_column = end_column; j++; } } } } } g_ptr_array_free (il_offset_array, TRUE); g_ptr_array_free (line_number_array, TRUE); g_ptr_array_free (hidden_array, TRUE); mono_debugger_unlock (); return; }
const char *obs_source_getdisplayname(enum obs_source_type type, const char *id, const char *locale) { const struct source_info *info = get_source_info(type, id); return (info != NULL) ? info->getname(locale) : NULL; }
obs_data_t obs_source_settings(enum obs_source_type type, const char *id) { const struct obs_source_info *info = get_source_info(type, id); return (info) ? get_defaults(info) : NULL; }