예제 #1
0
    def test_computed_gotos(self):
        # Test for toolchain bug.
        # Bug 1:  gcc outputs "jmp *%eax", fails to validate.
        # Bug 2:  gcc outputs "nacljmp *%eax", fails to assemble.
        # Correct assembly output is "nacljmp %eax".
        code = """
int foo(int i) {
  void *addr[] = { &&label1, &&label2 };
  goto *addr[i];
 label1:
  return 1234;
 label2:
  return 4568;
}

int main() {
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "code.c"), code)
        # ncval doesn't seem to accept .o files any more.
        # TODO: fix ncval.
        testutils.check_call([
            "nacl-gcc",  # "-c",
            os.path.join(temp_dir, "code.c"),
            "-o",
            os.path.join(temp_dir, "prog")
        ])
        run_ncval(os.path.join(temp_dir, "prog"))
  def test_ncval_handles_many_errors(self):
    # This tests for
    # http://code.google.com/p/nativeclient/issues/detail?id=915,
    # where ncval_annotate would truncate the number of results at 100.
    disallowed = """
#ifdef __i386__
  __asm__("int $0x80");
#else
#  error Update this test for other architectures!
#endif
"""
    source = "int main() { %s }" % (disallowed * 150)
    temp_dir = self.make_temp_dir()
    source_file = os.path.join(temp_dir, "code.c")
    write_file(source_file, source)
    testutils.check_call(["nacl-gcc", "-g", source_file,
                          "-o", os.path.join(temp_dir, "prog")])
    dest_file = os.path.join(self.make_temp_dir(), "file")
    subprocess.call([sys.executable,
                     os.path.join(PARENT_DIR, "ncval_annotate.py"),
                     os.path.join(temp_dir, "prog")],
                    stdout=open(dest_file, "w"))
    failures = len([line for line in open(dest_file, "r")
                    if line.startswith("VALIDATOR")])
    self.assertEquals(failures, 150)
    def test_custom_linker_scripts_via_search_path(self):
        # Check that the linker will pick up linker scripts from the
        # "ldscripts" directory in the library search path (which is
        # specified with -L).
        # To test this, try to link to a symbol that is defined in our
        # example linker script.
        temp_dir = self.make_temp_dir()
        os.mkdir(os.path.join(temp_dir, "ldscripts"))
        write_file(
            os.path.join(temp_dir, "ldscripts", "elf_nacl.x"),
            """
foo = 0x1234;
""",
        )
        write_file(
            os.path.join(temp_dir, "prog.c"),
            """
void foo();
int _start() {
  foo();
  return 0;
}
""",
        )
        testutils.check_call(
            [
                "nacl-gcc",
                "-nostartfiles",
                "-nostdlib",
                "-L%s" % temp_dir,
                os.path.join(temp_dir, "prog.c"),
                "-o",
                os.path.join(temp_dir, "prog"),
            ]
        )
예제 #4
0
    def test_ncval_handles_many_errors(self):
        # This tests for
        # http://code.google.com/p/nativeclient/issues/detail?id=915,
        # where ncval_annotate would truncate the number of results at 100.
        disallowed = """
#if defined(__i386__) || defined(__x86_64__)
  __asm__("int $0x80");
#else
#  error Update this test for other architectures!
#endif
"""
        source = "void _start() { %s }" % (disallowed * 150)
        temp_dir = self.make_temp_dir()
        source_file = os.path.join(temp_dir, "code.c")
        write_file(source_file, source)
        testutils.check_call([
            "x86_64-nacl-gcc", "-g", "-nostartfiles", "-nostdlib", source_file,
            "-o",
            os.path.join(temp_dir, "prog")
        ] + NACL_CFLAGS)
        dest_file = os.path.join(self.make_temp_dir(), "file")
        subprocess.call([
            sys.executable,
            os.path.join(PARENT_DIR, "ncval_annotate.py"),
            os.path.join(temp_dir, "prog")
        ],
                        stdout=open(dest_file, "w"))
        failures = len([
            line for line in open(dest_file, "r")
            if line.startswith("VALIDATOR")
        ])
        self.assertEquals(failures, 150)
    def test_computed_gotos(self):
        # Test for toolchain bug.
        # Bug 1:  gcc outputs "jmp *%eax", fails to validate.
        # Bug 2:  gcc outputs "nacljmp *%eax", fails to assemble.
        # Correct assembly output is "nacljmp %eax".
        code = """
int foo(int i) {
  void *addr[] = { &&label1, &&label2 };
  goto *addr[i];
 label1:
  return 1234;
 label2:
  return 4568;
}

int main() {
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "code.c"), code)
        # ncval doesn't seem to accept .o files any more.
        # TODO: fix ncval.
        testutils.check_call(
            ["nacl-gcc", os.path.join(temp_dir, "code.c"), "-o", os.path.join(temp_dir, "prog")]  # "-c",
        )
        run_ncval(os.path.join(temp_dir, "prog"))
  def test_ncval_handles_many_errors(self):
    # This tests for
    # http://code.google.com/p/nativeclient/issues/detail?id=915,
    # where ncval_annotate would truncate the number of results at 100.
    disallowed = """
#if defined(__i386__) || defined(__x86_64__)
  __asm__("int $0x80");
#else
#  error Update this test for other architectures!
#endif
"""
    source = "void _start() { %s }" % (disallowed * 150)
    temp_dir = self.make_temp_dir()
    source_file = os.path.join(temp_dir, "code.c")
    write_file(source_file, source)
    testutils.check_call(["x86_64-nacl-gcc", "-g", "-nostartfiles", "-nostdlib",
                          source_file,
                          "-o", os.path.join(temp_dir, "prog")] + NACL_CFLAGS)
    dest_file = os.path.join(self.make_temp_dir(), "file")
    subprocess.call([sys.executable,
                     os.path.join(ANNOTATE_DIR, "ncval_annotate.py"),
                     os.path.join(temp_dir, "prog")],
                    stdout=open(dest_file, "w"))
    # Filter unrecognized instructions that are printed, one per bundle.
    filter_pattern = ".*<<<<$"
    failures = len([line for line in open(dest_file, "r")
                    if re.match(filter_pattern, line)])
    self.assertEquals(failures, 10)
예제 #7
0
    def test_ncval_returns_errors(self):
        # Check that ncval returns a non-zero return code when there is a
        # validation failure.
        source = """
int main() {
#ifdef __i386__
  __asm__("ret"); /* This comment appears in output */
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        source_file = os.path.join(temp_dir, "code.c")
        write_file(source_file, source)
        testutils.check_call([
            "nacl-gcc", "-g", source_file, "-o",
            os.path.join(temp_dir, "prog")
        ])
        dest_file = os.path.join(self.make_temp_dir(), "file")
        rc = subprocess.call([
            sys.executable,
            os.path.join(PARENT_DIR, "ncval_annotate.py"),
            os.path.join(temp_dir, "prog")
        ],
                             stdout=open(dest_file, "w"))
        # ncval_annotate should propagate the exit code through so that it
        # can be used as a substitute for ncval.
        self.assertEquals(rc, 1)

        # For some reason ncval produces two errors for the same instruction.
        # TODO(mseaborn): Tidy that up.
        expected = """
VALIDATOR: ADDRESS: ret instruction (not allowed)
  code: c3                   	ret    
  func: main
  file: FILENAME:4
    __asm__("ret"); /* This comment appears in output */

VALIDATOR: ADDRESS: Illegal instruction
  code: c3                   	ret    
  func: main
  file: FILENAME:4
    __asm__("ret"); /* This comment appears in output */
"""
        expected_pattern = re.escape(expected)
        expected_pattern = expected_pattern.replace("ADDRESS", "[0-9a-f]+")
        # Cygwin mixes \ and / in filenames, so be liberal in what we accept.
        expected_pattern = expected_pattern.replace("FILENAME", "\S+code.c")

        actual = read_file(dest_file).replace("\r", "")
        if re.match(expected_pattern + "$", actual) is None:
            raise AssertionError(
                "Output did not match.\n\nEXPECTED:\n%s\nACTUAL:\n%s" %
                (expected, actual))
예제 #8
0
    def test_ncval_returns_errors(self):
        # Check that ncval returns a non-zero return code when there is a
        # validation failure.
        source = """
void _start() {
#if defined(__i386__) || defined(__x86_64__)
  __asm__("ret"); /* This comment appears in output */
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        source_file = os.path.join(temp_dir, "code.c")
        write_file(source_file, source)
        testutils.check_call([
            "x86_64-nacl-gcc", "-g", "-nostartfiles", "-nostdlib", source_file,
            "-o",
            os.path.join(temp_dir, "prog")
        ] + NACL_CFLAGS)
        dest_file = os.path.join(self.make_temp_dir(), "file")
        rc = subprocess.call([
            sys.executable,
            os.path.join(ANNOTATE_DIR, "ncval_annotate.py"),
            os.path.join(temp_dir, "prog")
        ],
                             stdout=open(dest_file, "w"))
        # ncval_annotate should propagate the exit code through so that it
        # can be used as a substitute for ncval.
        self.assertEquals(rc, 1)

        # Errors printed in two lines, with interspersed objdump output.
        # The first line starts with an ADDRESS and file/line.
        # The second is the error on the instruction, which ends with "<<<<".
        filter_pattern = "^[0-9a-f]+.*|.*<<<<$"
        actual_lines = [
            line for line in open(dest_file, "r")
            if re.match(filter_pattern, line)
        ]
        actual = "".join(actual_lines)
        # Strip windows' carriage return characters.
        actual = actual.replace("\r", "")

        expected_pattern = """
ADDRESS \(FILENAME:[0-9]+, function _start\): unrecognized instruction
\s+ADDRESS:\s+c3\s+retq?\s+<<<<
"""
        expected_pattern = expected_pattern.replace("ADDRESS", "[0-9a-f]+")
        # Cygwin mixes \ and / in filenames, so be liberal in what we accept.
        expected_pattern = expected_pattern.replace("FILENAME", "code.c")

        if re.match(expected_pattern, "\n" + actual) is None:
            raise AssertionError(
                "Output did not match.\n\nEXPECTED:\n%s\nACTUAL:\n%s" %
                (expected_pattern, actual))
  def test_ncval_returns_errors(self):
    # Check that ncval returns a non-zero return code when there is a
    # validation failure.
    source = """
int main() {
#ifdef __i386__
  __asm__("ret"); /* This comment appears in output */
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
    temp_dir = self.make_temp_dir()
    source_file = os.path.join(temp_dir, "code.c")
    write_file(source_file, source)
    testutils.check_call(["nacl-gcc", "-g", source_file,
                          "-o", os.path.join(temp_dir, "prog")])
    dest_file = os.path.join(self.make_temp_dir(), "file")
    rc = subprocess.call([sys.executable,
                          os.path.join(PARENT_DIR, "ncval_annotate.py"),
                          os.path.join(temp_dir, "prog")],
                         stdout=open(dest_file, "w"))
    # ncval_annotate should propagate the exit code through so that it
    # can be used as a substitute for ncval.
    self.assertEquals(rc, 1)

    # For some reason ncval produces two errors for the same instruction.
    # TODO(mseaborn): Tidy that up.
    expected = """
VALIDATOR: ADDRESS: ret instruction (not allowed)
  code: c3                   	ret    
  func: main
  file: FILENAME:4
    __asm__("ret"); /* This comment appears in output */

VALIDATOR: ADDRESS: Illegal instruction
  code: c3                   	ret    
  func: main
  file: FILENAME:4
    __asm__("ret"); /* This comment appears in output */
"""
    expected_pattern = re.escape(expected)
    expected_pattern = expected_pattern.replace("ADDRESS", "[0-9a-f]+")
    # Cygwin mixes \ and / in filenames, so be liberal in what we accept.
    expected_pattern = expected_pattern.replace("FILENAME", "\S+code.c")

    actual = read_file(dest_file).replace("\r", "")
    if re.match(expected_pattern + "$", actual) is None:
      raise AssertionError(
        "Output did not match.\n\nEXPECTED:\n%s\nACTUAL:\n%s"
        % (expected, actual))
  def test_ncval_returns_errors(self):
    # Check that ncval returns a non-zero return code when there is a
    # validation failure.
    source = """
void _start() {
#if defined(__i386__) || defined(__x86_64__)
  __asm__("ret"); /* This comment appears in output */
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
    temp_dir = self.make_temp_dir()
    source_file = os.path.join(temp_dir, "code.c")
    write_file(source_file, source)
    testutils.check_call(["x86_64-nacl-gcc", "-g", "-nostartfiles", "-nostdlib",
                          source_file,
                          "-o", os.path.join(temp_dir, "prog")] + NACL_CFLAGS)
    dest_file = os.path.join(self.make_temp_dir(), "file")
    rc = subprocess.call([sys.executable,
                          os.path.join(ANNOTATE_DIR, "ncval_annotate.py"),
                          os.path.join(temp_dir, "prog")],
                         stdout=open(dest_file, "w"))
    # ncval_annotate should propagate the exit code through so that it
    # can be used as a substitute for ncval.
    self.assertEquals(rc, 1)

    # Errors printed in two lines, with interspersed objdump output.
    # The first line starts with an ADDRESS and file/line.
    # The second is the error on the instruction, which ends with "<<<<".
    filter_pattern = "^[0-9a-f]+.*|.*<<<<$"
    actual_lines = [line for line in open(dest_file, "r")
                    if re.match(filter_pattern, line)]
    actual = "".join(actual_lines)
    # Strip windows' carriage return characters.
    actual = actual.replace("\r", "")

    expected_pattern = """
ADDRESS \(FILENAME:[0-9]+, function _start\): unrecognized instruction
\s+ADDRESS:\s+c3\s+retq?\s+<<<<
"""
    expected_pattern = expected_pattern.replace("ADDRESS", "[0-9a-f]+")
    # Cygwin mixes \ and / in filenames, so be liberal in what we accept.
    expected_pattern = expected_pattern.replace("FILENAME", "code.c")

    if re.match(expected_pattern, "\n" + actual) is None:
      raise AssertionError(
        "Output did not match.\n\nEXPECTED:\n%s\nACTUAL:\n%s"
        % (expected_pattern, actual))
예제 #11
0
    def test_library_plt_entries(self):
        # Checks that the PLT entries generated by ld for relocatable
        # (PIC) objects pass the validator.
        library_code = """
void bar(void);
void foo(void) {
  bar(); /* Linker creates a PLT entry for this reference. */
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "code.c"), library_code)
        testutils.check_call([
            "nacl-gcc", "-nostdlib", "-shared", "-fPIC",
            "-Wl,-T,%s" % os.path.join(LDSCRIPTS_DIR, "elf_nacl.xs"),
            os.path.join(temp_dir, "code.c"), "-o",
            os.path.join(temp_dir, "code.so")
        ])
        run_ncval(os.path.join(temp_dir, "code.so"))
    def test_ncval_returns_errors(self):
        # Check that ncval returns a non-zero return code when there is a
        # validation failure.
        code = """
int main() {
#ifdef __i386__
  __asm__("ret");
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "code.c"), code)
        testutils.check_call(["nacl-gcc", os.path.join(temp_dir, "code.c"), "-o", os.path.join(temp_dir, "prog")])
        rc = subprocess.call(["ncval", os.path.join(temp_dir, "prog")], stdout=open(os.devnull, "w"))
        self.assertEquals(rc, 1)
예제 #13
0
    def test_ncval_returns_errors(self):
        # Check that ncval returns a non-zero return code when there is a
        # validation failure.
        code = """
int main() {
#ifdef __i386__
  __asm__("ret");
#else
#  error Update this test for other architectures!
#endif
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "code.c"), code)
        testutils.check_call([
            "nacl-gcc",
            os.path.join(temp_dir, "code.c"), "-o",
            os.path.join(temp_dir, "prog")
        ])
        rc = subprocess.call(["ncval", os.path.join(temp_dir, "prog")],
                             stdout=open(os.devnull, "w"))
        self.assertEquals(rc, 1)
예제 #14
0
    def test_custom_linker_scripts_via_search_path(self):
        # Check that the linker will pick up linker scripts from the
        # "ldscripts" directory in the library search path (which is
        # specified with -L).
        # To test this, try to link to a symbol that is defined in our
        # example linker script.
        temp_dir = self.make_temp_dir()
        os.mkdir(os.path.join(temp_dir, "ldscripts"))
        write_file(os.path.join(temp_dir, "ldscripts", "elf_nacl.x"), """
foo = 0x1234;
""")
        write_file(os.path.join(temp_dir, "prog.c"), """
void foo();
int _start() {
  foo();
  return 0;
}
""")
        testutils.check_call([
            "nacl-gcc", "-nostartfiles", "-nostdlib",
            "-L%s" % temp_dir,
            os.path.join(temp_dir, "prog.c"), "-o",
            os.path.join(temp_dir, "prog")
        ])
예제 #15
0
    def test_executable_plt_entries(self):
        # Checks that the PLT entries generated by ld for non-relocatable
        # (non-PIC) objects pass the validator.
        library_code = """
void foo(void) {
}
"""
        executable_code = """
void foo(void);
int _start(void) {
  foo(); /* Linker creates a PLT entry for this reference. */
  return 0;
}
"""
        temp_dir = self.make_temp_dir()
        write_file(os.path.join(temp_dir, "library.c"), library_code)
        write_file(os.path.join(temp_dir, "executable.c"), executable_code)
        testutils.check_call([
            "nacl-gcc", "-nostdlib", "-shared", "-fPIC",
            "-Wl,-T,%s" % os.path.join(LDSCRIPTS_DIR, "elf_nacl.xs"),
            os.path.join(temp_dir, "library.c"), "-o",
            os.path.join(temp_dir, "library.so")
        ])
        # TODO: Make this work with elf_nacl.x.
        # elf_nacl.xs is supposed to be for shared libraries, not executables.
        testutils.check_call([
            "nacl-gcc", "-nostdlib", "-fPIC",
            "-Wl,-T,%s" % os.path.join(LDSCRIPTS_DIR, "elf_nacl.xs"),
            os.path.join(temp_dir, "executable.c"),
            os.path.join(temp_dir, "library.so"), "-o",
            os.path.join(temp_dir, "prog")
        ])
        run_ncval(os.path.join(temp_dir, "prog"))
        # Also validate the library as a sanity check, but it shouldn't
        # contain any PLT entries.
        run_ncval(os.path.join(temp_dir, "library.so"))