C++ SDK Question when use til

when I load a Windows PE file, IDA auto load 2 til: ntapi64_win7 & mssdk64_win7

and when I use type MACRO_ERROR, I found that it was being defined twice.

so when I set num expr to enum, it’s will be confused, general it’s use ntapi64_win7’s MACRO_ERROR not mssdk64_win7.

static const char error_type[] = "MACRO_ERROR";
[...]

  // create a new expression
  cexpr_t *num_expr = make_num(HRESULT_CODE(value), nullptr, BADADDR, 0, no_sign, sizeof(int64_t));

  num_expr->n->nf.type_name = error_type;
  num_expr->n->nf.props |= NF_VALID;
  num_expr->n->nf.serial = 0;
  num_expr->n->nf.flags = enum_flag();
  num_expr->type.get_named_type(nullptr, error_type, BTF_ENUM);
[...]

so I try to use load_til manually:

[...]
  qstring errbuf;
  til_t *til = load_til("mssdk_win7", &errbuf);
  if (til == nullptr)
  {
    msg("Failed to load til: %s\n", errbuf.c_str());
    return;
  }

[...]

  // create a new expression
  cexpr_t *num_expr = make_num(HRESULT_CODE(value), nullptr, BADADDR, 0, no_sign, sizeof(int64_t));

  num_expr->n->nf.type_name = error_type;
  num_expr->n->nf.props |= NF_VALID;
  num_expr->n->nf.serial = 0;
  num_expr->n->nf.flags = enum_flag();
  num_expr->type.get_named_type(til, error_type, BTF_ENUM);

[...] // maybe we need free til after plugin uninstall

unfortunately, it’s looks like nothing has changed…

BTW, another question is, when I self-modified ctree, expr( op = cot_num ) seems cannot to convert(create) enum / hex / oct / …

it’s my issue or expected behavior?

If i understand correctly, before IDA9, enum type should be imported to local til first by import_type(). Not sure is it need for IDA9 and later. And then enum type might be referenced by name with create_typedef()
Please look makeEnumExpr for example

seems import_type has been removed in IDA9, and hrtng do nothing in IDA9 :thinking:, see

while importing a type explicitly is no longer necessary, you can still force a local copy which will take precedence over types in loaded types libraries. This can be done using the force_tid() method if you have a tinfo_t reference (e.g. see idc.import_type(), or copy_named_type otherwise. To import from a specific base TIL, you could use something like:

lti = ida_typeinf.get_idati()
for i in range(lti.nbases):
   bti = lti.base(i)
   if bti.name=="mssdk_win7":
       ord = ida_typeinf.copy_named_type(lti, bti, "MACRO_ERROR")
3 Likes

thx! I use this resolved my issue.

  til_t *lti = get_idati();
  til_t *bti = lti->find_base(inf_is_64bit() ? "mssdk64_win7" : "mssdk_win7");
  FASSERT(bti, nullptr);
  int ord = copy_named_type(lti, bti, enum_name.c_str());