dwarf_loader: Use libdw__lock for dwarf_getlocation(s)
[dwarves.git] / syscse.c
blobb09c8564759dab76c6b1f897b55c7360efa41cb4
1 /*
2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2007-2016 Arnaldo Carvalho de Melo <acme@kernel.org>
6 System call sign extender
7 */
9 #include <argp.h>
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
15 #include "dwarves.h"
16 #include "dutil.h"
18 static const char *prefix = "sys_";
19 static size_t prefix_len = 4;
21 static struct conf_fprintf conf;
23 static struct conf_load conf_load = {
24 .conf_fprintf = &conf,
27 static bool filter(struct function *f)
29 if (f->proto.nr_parms != 0) {
30 const char *name = function__name(f);
32 if (strlen(name) > prefix_len &&
33 memcmp(name, prefix, prefix_len) == 0)
34 return false;
36 return true;
39 static void zero_extend(const int regparm, const struct base_type *bt, const char *parm)
41 const char *instr = "INVALID";
43 switch (bt->bit_size) {
44 case 32:
45 instr = "sll";
46 break;
47 case 16:
48 instr = "slw";
49 break;
50 case 8:
51 instr = "slb";
52 break;
55 char bf[64];
56 printf("\t%s\t$a%d, $a%d, 0"
57 "\t/* zero extend $a%d(%s %s) from %d to 64-bit */\n",
58 instr, regparm, regparm, regparm,
59 base_type__name(bt, bf, sizeof(bf)),
60 parm, bt->bit_size);
63 static void emit_wrapper(struct function *f, struct cu *cu)
65 struct parameter *parm;
66 const char *name = function__name(f);
67 int regparm = 0, needs_wrapper = 0;
69 function__for_each_parameter(f, cu, parm) {
70 const type_id_t type_id = parm->tag.type;
71 struct tag *type = cu__type(cu, type_id);
73 tag__assert_search_result(type, parm->tag.tag, parameter__name(parm));
74 if (type->tag == DW_TAG_base_type) {
75 struct base_type *bt = tag__base_type(type);
76 char bf[64];
78 if (bt->bit_size < 64 &&
79 strncmp(base_type__name(bt, bf, sizeof(bf)), "unsigned", 8) == 0) {
80 if (!needs_wrapper) {
81 printf("wrap_%s:\n", name);
82 needs_wrapper = 1;
84 zero_extend(regparm, bt, parameter__name(parm));
87 ++regparm;
90 if (needs_wrapper)
91 printf("\tj\t%s\n\n", name);
94 static int cu__emit_wrapper(struct cu *cu, void *cookie __maybe_unused)
96 struct function *pos;
97 uint32_t id;
99 cu__for_each_function(cu, id, pos)
100 if (!filter(pos))
101 emit_wrapper(pos, cu);
102 return 0;
105 static void cus__emit_wrapper(struct cus *cu)
107 cus__for_each_cu(cu, cu__emit_wrapper, NULL, NULL);
110 /* Name and version of program. */
111 ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
113 static const struct argp_option options[] = {
115 .key = 'p',
116 .name = "prefix",
117 .arg = "PREFIX",
118 .doc = "function prefix",
121 .name = NULL,
125 static error_t options_parser(int key, char *arg, struct argp_state *state)
127 switch (key) {
128 case ARGP_KEY_INIT:
129 if (state->child_inputs != NULL)
130 state->child_inputs[0] = state->input;
131 break;
132 case 'p':
133 prefix = arg;
134 prefix_len = strlen(prefix);
135 break;
136 default:
137 return ARGP_ERR_UNKNOWN;
139 return 0;
142 static const char args_doc[] = "FILE";
144 static struct argp argp = {
145 .options = options,
146 .parser = options_parser,
147 .args_doc = args_doc,
150 int main(int argc, char *argv[])
152 int err, remaining;
153 struct cus *cus = cus__new();
155 if (cus == NULL) {
156 fprintf(stderr, "%s: insufficient memory\n", argv[0]);
157 return EXIT_FAILURE;
160 if (argp_parse(&argp, argc, argv, 0, &remaining, NULL) ||
161 remaining == argc) {
162 argp_help(&argp, stderr, ARGP_HELP_SEE, argv[0]);
163 return EXIT_FAILURE;
165 err = cus__load_files(cus, &conf_load, argv + remaining);
166 if (err != 0) {
167 cus__fprintf_load_files_err(cus, "syscse", argv + remaining, err, stderr);
168 return EXIT_FAILURE;
171 cus__emit_wrapper(cus);
172 return EXIT_SUCCESS;