Lines Matching +full:count +full:- +full:width
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
17 #include <tools/dis-asm-compat.h>
51 int width; /* formatting width */
60 #define DALT_DEFAULT(dalt) (!(dalt)->alt)
61 #define DALT_INSN(dalt) (DALT_DEFAULT(dalt) ? (dalt)->orig_insn : (dalt)->alt->insn)
62 #define DALT_GROUP(dalt) (DALT_INSN(dalt)->alt_group)
63 #define DALT_ALTID(dalt) ((dalt)->orig_insn->offset)
68 #define ALT_FEATURE_MASK ((1 << ALT_FLAGS_SHIFT) - 1)
94 return rv == -1 ? NULL : str;
110 ((*(dinfo)->fprintf_func)((dinfo)->stream, __VA_ARGS__))
117 char *buf = dctx->result;
121 if (len >= DISAS_RESULT_SIZE - 1) {
122 WARN_FUNC(dctx->insn->sec, dctx->insn->offset,
124 return -1;
126 avail = DISAS_RESULT_SIZE - len;
130 WARN_FUNC(dctx->insn->sec, dctx->insn->offset,
132 return -1;
174 sprint_name(symstr, sym->name, addr - sym->offset);
185 struct disas_context *dctx = dinfo->application_data;
200 if (!dctx->alt_applied)
203 alt_group = dctx->insn->alt_group;
204 if (!alt_group || !alt_group->orig_group ||
205 addr < alt_group->first_insn->offset ||
206 addr > alt_group->last_insn->offset)
209 orig_first_insn = alt_group->orig_group->first_insn;
210 offset = addr - alt_group->first_insn->offset;
212 addr = orig_first_insn->offset + offset;
213 sym = orig_first_insn->sym;
215 disas_print_addr_sym(orig_first_insn->sec, sym, addr, dinfo);
223 struct disas_context *dctx = dinfo->application_data;
224 struct instruction *insn = dctx->insn;
230 if (insn->sym && addr >= insn->sym->offset &&
231 addr < insn->sym->offset + insn->sym->len) {
232 sym = insn->sym;
235 disas_print_addr_sym(insn->sec, sym, addr, dinfo);
240 struct disas_context *dctx = dinfo->application_data;
241 struct instruction *insn = dctx->insn;
247 reloc = find_reloc_by_dest_range(dctx->file->elf, insn->sec,
248 insn->offset, insn->len);
267 if (is_sec_sym(reloc->sym)) {
268 str = offstr(reloc->sym->sec, reloc->sym->offset + offset);
272 sprint_name(symstr, reloc->sym->name, offset);
282 struct disas_context *dctx = dinfo->application_data;
283 struct instruction *insn = dctx->insn;
293 jump_dest = insn->jump_dest;
294 if (jump_dest && jump_dest->sym && jump_dest->offset == addr) {
296 disas_print_addr_sym(jump_dest->sec, jump_dest->sym,
308 is_reloc = (addr == insn->offset + insn->len);
315 if (sym && (sym->offset == addr || (sym->offset == 0 && is_reloc))) {
316 DINFO_FPRINTF(dinfo, bfd_vma_fmt, addr, sym->name);
327 * Initialize disassemble info arch, mach (32 or 64-bit) and options.
333 struct disas_context *dctx = dinfo->application_data;
334 struct objtool_file *file = dctx->file;
336 dinfo->arch = arch;
338 switch (file->elf->ehdr.e_ident[EI_CLASS]) {
340 dinfo->mach = mach32;
343 dinfo->mach = mach64;
346 return -1;
349 dinfo->disassembler_options = options;
366 dctx->file = file;
367 dinfo = &dctx->info;
372 dinfo->read_memory_func = buffer_read_memory;
373 dinfo->print_address_func = disas_print_address;
374 dinfo->application_data = dctx;
383 dinfo->arch = bfd_arch_unknown;
384 dinfo->mach = 0;
387 if (err || dinfo->arch == bfd_arch_unknown || dinfo->mach == 0) {
392 dinfo->endian = (file->elf->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) ?
397 dctx->disassembler = disassembler(dinfo->arch,
398 dinfo->endian == BFD_ENDIAN_BIG,
399 dinfo->mach, NULL);
400 if (!dctx->disassembler) {
419 return dctx->result;
450 n += fprintf(stream, "%6lx: %-*s ", offset, len, addr_str);
454 n += fprintf(stream, "%-*s", len, "");
494 sec = insn->sec;
495 off = insn->offset;
524 fake_nop = (!insn->sec && insn->type == INSN_NOP);
526 snprintf(fake_nop_insn, 32, "<fake nop> (%d bytes)", insn->len);
534 len = (depth + 1) * 2 < DISAS_INSN_SPACE ? DISAS_INSN_SPACE - (depth+1) * 2 : 1;
535 disas_print_info(stream, insn, depth, "%-*s", len, insn_str);
546 fprintf(stream, " - ");
556 * alternative (i.e. insn->alt_group != NULL), and it is disassembled
559 * these references will be re-adjusted to replace the original code.
565 disassembler_ftype disasm = dctx->disassembler;
566 struct disassemble_info *dinfo = &dctx->info;
568 dctx->insn = insn;
569 dctx->alt_applied = alt_applied;
570 dctx->result[0] = '\0';
572 if (insn->type == INSN_NOP) {
573 DINFO_FPRINTF(dinfo, "nop%d", insn->len);
574 return insn->len;
581 dinfo->buffer = insn->sec->data->d_buf;
582 dinfo->buffer_vma = 0;
583 dinfo->buffer_length = sec_size(insn->sec);
585 return disasm(insn->offset, &dctx->info);
603 if (alt_grp->last_insn == insn || alt_grp->nop == insn)
610 for (insn = alt_grp->first_insn; \
630 for (alt = insn->alts; alt; alt = alt->next) {
631 if (alt->type == ALT_TYPE_INSTRUCTIONS) {
636 switch (alt->type) {
664 switch (alt->type) {
676 * This is a non-default group alternative. Create a name
689 if (!alt->insn->alt_group)
692 feature = alt->insn->alt_group->feature;
724 dalt->orig_insn = orig_insn;
725 dalt->alt = alt;
726 dalt->insn_idx = 0;
727 dalt->name = alt ? disas_alt_name(alt) : strdup("DEFAULT");
728 if (!dalt->name)
729 return -1;
730 dalt->width = strlen(dalt->name);
742 DALT_ALTID(dalt), dalt->name);
743 return -1;
747 dalt->insn[index].str = insn_str;
748 dalt->insn[index].offset = offset;
749 dalt->insn[index].nops = nops;
750 if (len > dalt->width)
751 dalt->width = len;
764 orig_insn = dalt->orig_insn;
765 dest_insn = dalt->alt->insn;
767 if (orig_insn->type == INSN_NOP) {
768 if (orig_insn->len == 5)
770 str = strfmt("jmp%-3s %lx <%s+0x%lx>", suffix,
771 dest_insn->offset, dest_insn->sym->name,
772 dest_insn->offset - dest_insn->sym->offset);
775 str = strfmt("nop%d", orig_insn->len);
776 nops = orig_insn->len;
780 return -1;
795 alt_insn = dalt->alt->insn;
797 alt_insn->offset, alt_insn->sym->name,
798 alt_insn->offset - alt_insn->sym->offset);
800 return -1;
817 int count;
821 file = dctx->file;
822 count = 0;
831 return -1;
833 nops = insn->type == INSN_NOP ? insn->len : 0;
834 err = disas_alt_add_insn(dalt, count, str, offset, nops);
837 offset += insn->len;
838 count++;
841 return count;
862 disas_insn(dctx, dalt->orig_insn);
865 return -1;
866 nops = dalt->orig_insn->type == INSN_NOP ? dalt->orig_insn->len : 0;
869 return -1;
879 * Return the offset for the next instructions to print, or -1 if all
890 offset_next = -1;
894 j = dalt->insn_idx;
895 if (j == -1) {
896 printf("| %-*s ", dalt->width, "");
900 if (dalt->insn[j].offset == offset) {
901 str = dalt->insn[j].str;
902 printf("| %-*s ", dalt->width, str ?: "");
904 dalt->insn_idx = j;
906 dalt->insn_idx = -1;
910 printf("| %-*s ", dalt->width, "");
913 if (dalt->insn[j].offset > 0 &&
914 (offset_next == -1 ||
915 (dalt->insn[j].offset < offset_next)))
916 offset_next = dalt->insn[j].offset;
924 * Print all alternatives side-by-side.
939 disas_print_info(stdout, orig_insn, -2, NULL);
941 if (strlen(alt_name) > dalts[0].width)
942 dalts[0].width = strlen(alt_name);
943 printf("| %-*s ", dalts[0].width, alt_name);
946 printf("| %-*s ", dalts[i].width, dalts[i].name);
956 disas_print(stdout, orig_insn->sec, orig_insn->offset + offset,
957 -2, NULL);
970 int width;
976 len = disas_print(stdout, orig_insn->sec, orig_insn->offset, 0, NULL);
986 width = 0;
988 if (dalts[i].width > width)
989 width = dalts[i].width;
993 printf("%*s= %-*s (if %s)\n", len, "", width,
1005 disas_print(stdout, orig_insn->sec,
1006 orig_insn->offset + dalts[i].insn[j].offset, 0,
1027 int count;
1031 count = 0;
1037 for (j = insn_count - 1; j >= 0; j--) {
1038 if (!dalt->insn[j].str || !dalt->insn[j].nops)
1040 offset = dalt->insn[j].offset;
1041 free(dalt->insn[j].str);
1042 dalt->insn[j].offset = 0;
1043 dalt->insn[j].str = NULL;
1044 nops += dalt->insn[j].nops;
1050 * NOP instruction then re-add it. If there was a block of
1052 * covers (nop*<number-of-bytes>).
1056 dalt->insn[j + 1].str = strfmt("nop%s%d", s, nops);
1057 dalt->insn[j + 1].offset = offset;
1058 dalt->insn[j + 1].nops = nops;
1062 if (j > count)
1063 count = j;
1066 return count + 1;
1086 int count;
1091 orig_insn->offset);
1094 orig_insn->offset);
1117 for (alt = orig_insn->alts; alt; alt = alt->next) {
1130 count = -1;
1131 switch (dalt->alt->type) {
1133 count = disas_alt_group(dctx, dalt);
1136 count = disas_alt_extable(dalt);
1139 count = disas_alt_jump(dalt);
1142 if (count < 0) {
1144 alt_name, dalt->name);
1148 insn_count = count > insn_count ? count : insn_count;
1154 * Print default and non-default alternatives.
1164 last_insn = orig_insn->alt_group ? orig_insn->alt_group->last_insn :
1187 printf("%s:\n", func->name);
1188 sym_for_each_insn(dctx->file, func, insn) {
1189 if (insn->alts) {
1220 for_each_sym(dctx->file->elf, sym) {
1221 if (sym->warned)
1232 for_each_sec(dctx->file->elf, sec) {
1243 if (opts.verbose && sym->warned)
1246 if (disas_all || fnmatch(opts.disas, sym->name, 0) == 0)