[llvm-bugs] [Bug 51123] New: [LLVM-COV] Wrong coverage of label caused by an implicit goto statement.

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Jul 17 00:09:23 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=51123

            Bug ID: 51123
           Summary: [LLVM-COV] Wrong coverage of label caused by an
                    implicit  goto statement.
           Product: Runtime Libraries
           Version: 11.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: libprofile library
          Assignee: unassignedbugs at nondot.org
          Reporter: cnwy1996 at outlook.com
                CC: llvm-bugs at lists.llvm.org

$ clang -v
clang version 11.0.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/wangyang/llvm-project/build/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;@m64
Selected multilib: .;@m64

$ cat test.c
#include <stdlib.h>

typedef unsigned int uint32;
typedef signed int sint32;

typedef uint32 reg_t;

typedef unsigned long int host_addr_t;
typedef uint32 target_addr_t;
typedef sint32 target_saddr_t;

typedef union {
  struct {
    signed int offset : 18;
    unsigned int ignore : 4;
    unsigned int s1 : 8;
    int : 2;
    signed int simm : 14;
    unsigned int s3 : 8;
    unsigned int s2 : 8;
    int pad2 : 2;
  } f1;
  long long ll;
  double d;
} insn_t;

typedef struct {
  target_addr_t vaddr_tag;
  unsigned long int rigged_paddr;
} tlb_entry_t;

typedef struct {
  insn_t *pc;
  reg_t registers[256];
  insn_t *program;
  tlb_entry_t tlb_tab[0x100];
} environment_t;

enum operations { LOAD32_RR, METAOP_DONE };

host_addr_t f() { abort(); }

reg_t simulator_kernel(int what, environment_t *env) {
  register insn_t *pc = env->pc;
  register reg_t *regs = env->registers;
  register insn_t insn;
  register int s1;
  register reg_t r2;
  register void *base_addr = &&sim_base_addr;
  register tlb_entry_t *tlb = env->tlb_tab;

  if (what != 0) {
    int i;
    static void *op_map[] = {
        &&L_LOAD32_RR,
        &&L_METAOP_DONE,
    };
    insn_t *program = env->program;
    for (i = 0; i < what; i++)
      program[i].f1.offset = op_map[program[i].f1.offset] - base_addr;
  }

sim_base_addr:;

  insn = *pc++;
  r2 = (*(reg_t *)(((char *)regs) + (insn.f1.s2 << 2)));
  s1 = (insn.f1.s1 << 2);
  goto *(base_addr + insn.f1.offset);

L_LOAD32_RR : {
  target_addr_t vaddr_page = r2 / 4096;
  unsigned int x = vaddr_page % 0x100;
  insn = *pc++;

  for (;;) {
    target_addr_t tag = tlb[x].vaddr_tag;
    host_addr_t rigged_paddr = tlb[x].rigged_paddr;

    if (tag == vaddr_page) {
      goto *(base_addr + insn.f1.offset);
    }

    if (((target_saddr_t)tag < 0)) {

      goto *(base_addr + insn.f1.offset);
    }

    x = (x - 1) % 0x100;
  }

L_METAOP_DONE:
  return (*(reg_t *)(((char *)regs) + s1));
}
}

insn_t program[2 + 1];

void *malloc();

int main() {
  environment_t env;
  insn_t insn;
  int i, res;
  host_addr_t a_page = (host_addr_t)malloc(2 * 4096);
  target_addr_t a_vaddr = 0x123450;
  target_addr_t vaddr_page = a_vaddr / 4096;
  a_page = (a_page + 4096 - 1) & -4096;

  env.tlb_tab[((vaddr_page) % 0x100)].vaddr_tag = vaddr_page;
  env.tlb_tab[((vaddr_page) % 0x100)].rigged_paddr = a_page - vaddr_page *
4096;
  insn.f1.offset = LOAD32_RR;
  env.registers[0] = 0;
  env.registers[2] = a_vaddr;
  *(sint32 *)(a_page + a_vaddr % 4096) = 88;
  insn.f1.s1 = 0;
  insn.f1.s2 = 2;

  for (i = 0; i < 2; i++)
    program[i] = insn;

  insn.f1.offset = METAOP_DONE;
  insn.f1.s1 = 0;
  program[2] = insn;

  env.pc = program;
  env.program = program;

  res = simulator_kernel(2 + 1, &env);

}

$ clang -w -O0 -g -fcoverage-mapping -fprofile-instr-generate=test.profraw
test.c; ./a.out; llvm-profdata merge test.profraw -o test.profdata; llvm-cov
show a.out -instr-profile=test.profdata test.c > test.lcov; cat test.lcov
    1|       |#include <stdlib.h>
    2|       |
    3|       |typedef unsigned int uint32;
    4|       |typedef signed int sint32;
    5|       |
    6|       |typedef uint32 reg_t;
    7|       |
    8|       |typedef unsigned long int host_addr_t;
    9|       |typedef uint32 target_addr_t;
   10|       |typedef sint32 target_saddr_t;
   11|       |
   12|       |typedef union {
   13|       |  struct {
   14|       |    signed int offset : 18;
   15|       |    unsigned int ignore : 4;
   16|       |    unsigned int s1 : 8;
   17|       |    int : 2;
   18|       |    signed int simm : 14;
   19|       |    unsigned int s3 : 8;
   20|       |    unsigned int s2 : 8;
   21|       |    int pad2 : 2;
   22|       |  } f1;
   23|       |  long long ll;
   24|       |  double d;
   25|       |} insn_t;
   26|       |
   27|       |typedef struct {
   28|       |  target_addr_t vaddr_tag;
   29|       |  unsigned long int rigged_paddr;
   30|       |} tlb_entry_t;
   31|       |
   32|       |typedef struct {
   33|       |  insn_t *pc;
   34|       |  reg_t registers[256];
   35|       |  insn_t *program;
   36|       |  tlb_entry_t tlb_tab[0x100];
   37|       |} environment_t;
   38|       |
   39|       |enum operations { LOAD32_RR, METAOP_DONE };
   40|       |
   41|      0|host_addr_t f() { abort(); }
   42|       |
   43|      1|reg_t simulator_kernel(int what, environment_t *env) {
   44|      1|  register insn_t *pc = env->pc;
   45|      1|  register reg_t *regs = env->registers;
   46|      1|  register insn_t insn;
   47|      1|  register int s1;
   48|      1|  register reg_t r2;
   49|      1|  register void *base_addr = &&sim_base_addr;
   50|      1|  register tlb_entry_t *tlb = env->tlb_tab;
   51|      1|
   52|      1|  if (what != 0) {
   53|      1|    int i;
   54|      1|    static void *op_map[] = {
   55|      1|        &&L_LOAD32_RR,
   56|      1|        &&L_METAOP_DONE,
   57|      1|    };
   58|      1|    insn_t *program = env->program;
   59|      4|    for (i = 0; i < what; i++)
   60|      3|      program[i].f1.offset = op_map[program[i].f1.offset] -
base_addr;
   61|      1|  }
   62|      1|
   63|      1|sim_base_addr:;
   64|      1|
   65|      1|  insn = *pc++;
   66|      1|  r2 = (*(reg_t *)(((char *)regs) + (insn.f1.s2 << 2)));
   67|      1|  s1 = (insn.f1.s1 << 2);
   68|      1|  goto *(base_addr + insn.f1.offset);
   69|      1|
   70|      2|L_LOAD32_RR : {
   71|      2|  target_addr_t vaddr_page = r2 / 4096;
   72|      2|  unsigned int x = vaddr_page % 0x100;
   73|      2|  insn = *pc++;
   74|      2|
   75|      2|  for (;;) {
   76|      2|    target_addr_t tag = tlb[x].vaddr_tag;
   77|      2|    host_addr_t rigged_paddr = tlb[x].rigged_paddr;
   78|      2|
   79|      2|    if (tag == vaddr_page) {
   80|      2|      goto *(base_addr + insn.f1.offset);
   81|      2|    }
   82|      2|
   83|      2|    if (((target_saddr_t)tag < 0)) {
   84|      0|
   85|      0|      goto *(base_addr + insn.f1.offset);
   86|      0|    }
   87|      2|
   88|      2|    x = (x - 1) % 0x100;
   89|      2|  }
   90|      2|
   91|      2|L_METAOP_DONE:
   92|      1|  return (*(reg_t *)(((char *)regs) + s1));
   93|      2|}
   94|      2|}
   95|       |
   96|       |insn_t program[2 + 1];
   97|       |
   98|       |void *malloc();
   99|       |
  100|      1|int main() {
  101|      1|  environment_t env;
  102|      1|  insn_t insn;
  103|      1|  int i, res;
  104|      1|  host_addr_t a_page = (host_addr_t)malloc(2 * 4096);
  105|      1|  target_addr_t a_vaddr = 0x123450;
  106|      1|  target_addr_t vaddr_page = a_vaddr / 4096;
  107|      1|  a_page = (a_page + 4096 - 1) & -4096;
  108|      1|
  109|      1|  env.tlb_tab[((vaddr_page) % 0x100)].vaddr_tag = vaddr_page;
  110|      1|  env.tlb_tab[((vaddr_page) % 0x100)].rigged_paddr = a_page -
vaddr_page * 4096;
  111|      1|  insn.f1.offset = LOAD32_RR;
  112|      1|  env.registers[0] = 0;
  113|      1|  env.registers[2] = a_vaddr;
  114|      1|  *(sint32 *)(a_page + a_vaddr % 4096) = 88;
  115|      1|  insn.f1.s1 = 0;
  116|      1|  insn.f1.s2 = 2;
  117|      1|
  118|      3|  for (i = 0; i < 2; i++)
  119|      2|    program[i] = insn;
  120|      1|
  121|      1|  insn.f1.offset = METAOP_DONE;
  122|      1|  insn.f1.s1 = 0;
  123|      1|  program[2] = insn;
  124|      1|
  125|      1|  env.pc = program;
  126|      1|  env.program = program;
  127|      1|
  128|      1|  res = simulator_kernel(2 + 1, &env);
  129|      1|
  130|      1|}
  131|       |
  132|       |

Line 88 is supposed to not be unexecuted, and the coverage of line 91 should be
1

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210717/5b53161a/attachment-0001.html>


More information about the llvm-bugs mailing list