From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 56100 invoked by alias); 22 Oct 2019 06:47:01 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 56091 invoked by uid 89); 22 Oct 2019 06:47:01 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-12.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,KAM_STOCKGEN,SPF_PASS autolearn=ham version=3.3.1 spammy=notify, sk:interpr, 1101, Mini X-HELO: esa3.mentor.iphmx.com Received: from esa3.mentor.iphmx.com (HELO esa3.mentor.iphmx.com) (68.232.137.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 22 Oct 2019 06:46:57 +0000 IronPort-SDR: MJSKj5i9dYXFs7dz3yy//YwcsQtTzxfr6j8j/7NeWzecwilvwdNgx1z5jwY1dNRq5b5Pu2nqZs rvOOpb4VJ5d0LQRBCaMMQOmzZSx6Hb+wBkZ92PpGOs56rERWKG0/K3wAcqrNhkUKJS3n8bf3OQ JQ7JwFzrLa6tIvHJQnlrfMrofYuL/nrCeetKmYjI5mw+TV1kLVcdhDFsoA4WpdJqjAxISjrfzb FNh+DQ5DQZuWi58S8dLk1kqBna7NhwnwTz8MFLFSuomv/jgyyFJpbvBZU5GcuKvH7yuFvCtzcL gvI= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 21 Oct 2019 22:46:56 -0800 IronPort-SDR: atk0zXtBGvaEIXYi0NaBLmNvBO+M+evZsCttGdeEskWJn6CJwLkL4/vBgOGRLLA2nHnVamNKjo XvEUJzY7M1d1E6Be7Yw852ARlrbVU5meVYVh5BbM6L2UhIPkcIaYBLSFi5iLF+FisytzslEEJ8 GMnJYrUdxCzjaNRkIMKxJ98UBTp6e5Qu2V1h9beYI7ApqSmQrxgInpmCCAnvgMkzUlU96uAwv8 mBQ2FD9uNipOxRwBfKameBI+Zx/pZ93joy0PehomEPav2jNKGfaU+phYyjBc2G6wlhKVQ4RUGL s0A= Subject: Re: [PING][PATCH 2/2] Testsuite for varobj updation after symbol removal To: CC: References: <1571306592-24472-1-git-send-email-Saqlain_Raza@mentor.com> <1571306592-24472-3-git-send-email-Saqlain_Raza@mentor.com> From: Saqlain Raza Message-ID: Date: Tue, 22 Oct 2019 06:47:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: <1571306592-24472-3-git-send-email-Saqlain_Raza@mentor.com> Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 7bit Return-Path: saqlain_raza@mentor.com X-SW-Source: 2019-10/txt/msg00781.txt.bz2 Ping ! Thanks, Saqlain On 10/17/19 3:03 PM, Raza, Saqlain wrote: > This patch provides testcases for variable object updation after removing > symbols. Test programs are same as used for testing remove-symbol-file > command in gdb.base. sym-file-main.c is modified to just add a global > variable for which varible object is created in testsuite. > > Testing: > ======= > This is tested for x86 and arm-none-linux-gnueabi targets > using both simulator and real boards. > > 2019-10-17 Saqlain Raza > Taimoor Mirza > > * gdb.mi/mi-var-invalidate.exp: Add tests to check global > variable object change list is correct when its value is > updated before removing symbols. > * gdb.mi/sym-file-loader.c: New file. > * gdb.mi/sym-file-loader.h: New file. > * gdb.mi/sym-file-main.c: New file. > * gdb.mi/sym-file-lib.c: New file. > > Signed-off-by: Raza, Saqlain > --- > gdb/testsuite/ChangeLog | 11 + > gdb/testsuite/gdb.mi/mi-var-invalidate.exp | 68 ++++++ > gdb/testsuite/gdb.mi/sym-file-lib.c | 28 +++ > gdb/testsuite/gdb.mi/sym-file-loader.c | 355 +++++++++++++++++++++++++++++ > gdb/testsuite/gdb.mi/sym-file-loader.h | 101 ++++++++ > gdb/testsuite/gdb.mi/sym-file-main.c | 86 +++++++ > 6 files changed, 649 insertions(+) > create mode 100644 gdb/testsuite/gdb.mi/sym-file-lib.c > create mode 100644 gdb/testsuite/gdb.mi/sym-file-loader.c > create mode 100644 gdb/testsuite/gdb.mi/sym-file-loader.h > create mode 100644 gdb/testsuite/gdb.mi/sym-file-main.c > > diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog > index 395a3cc..82c3a57 100644 > --- a/gdb/testsuite/ChangeLog > +++ b/gdb/testsuite/ChangeLog > @@ -1,3 +1,14 @@ > +2019-10-17 Saqlain Raza > + Taimoor Mirza > + > + * gdb.mi/mi-var-invalidate.exp: Add tests to check global > + variable object change list is correct when its value is > + updated before removing symbols. > + * gdb.mi/sym-file-loader.c: New file. > + * gdb.mi/sym-file-loader.h: New file. > + * gdb.mi/sym-file-main.c: New file. > + * gdb.mi/sym-file-lib.c: New file. > + > 2019-10-16 Andrew Burgess > > * gdb.fortran/module.exp: Extend with 'info variables' test. > diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp > index e390968..b06e713 100644 > --- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp > +++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp > @@ -120,6 +120,74 @@ mi_gdb_test "-var-update global_simple" \ > mi_gdb_test "-var-info-type global_simple" \ > "\\^done,type=\"\"" \ > "no type for invalid variable global_simple" > +# Test varobj updation after removing symbols. > + > +#if {[skip_shlib_tests]} { > +# return 0 > +#} > + > +set target_size TARGET_UNKNOWN > +if {[is_lp64_target]} { > + set target_size TARGET_LP64 > +} elseif {[is_ilp32_target]} { > + set target_size TARGET_ILP32 > +} else { > + return 0 > +} > + > +set main_basename sym-file-main > +set loader_basename sym-file-loader > +set lib_basename sym-file-lib > + > +standard_testfile $main_basename.c $loader_basename.c $lib_basename.c > + > +set libsrc "${srcdir}/${subdir}/${srcfile3}" > +set test_bin_name "sym-test-file" > +set test_bin [standard_output_file ${test_bin_name}] > +set shlib_name [standard_output_file ${lib_basename}.so] > +set exec_opts [list debug "additional_flags= -I$srcdir/../../include/ \ > +-D$target_size -DSHLIB_NAME\\=\"$shlib_name\""] > + > +if [get_compiler_info] { > + return -1 > +} > + > +if {[gdb_compile_shlib $libsrc $shlib_name {debug}] != ""} { > + untested ${testfile} > + return -1 > +} > + > +if {[build_executable $testfile $test_bin "$srcfile $srcfile2" $exec_opts]} { > + return -1 > +} > + > +mi_delete_breakpoints > +mi_gdb_load ${test_bin} > + > +# Create varobj for count variable. > +mi_create_varobj var_count count "Create global varobj for count" > + > +# Run to GDB_ADD_SYMBOl_FILE in $srcfile for adding > +# $shlib_name. > +mi_runto gdb_add_symbol_file > + > +# Add $shlib_name using 'add-symbol-file'. > +mi_gdb_test "-interpreter-exec console \"add-symbol-file ${shlib_name} addr\"" \ > + "~\"add symbol table from file .*so.*at.*= $hex.*\\^done" \ > + "add-symbol-file ${shlib_name}" > + > +# Continue to gdb_remove_symbol_file in $srcfile. > +mi_runto gdb_remove_symbol_file > + > +# Remove $shlib_name using 'remove-symbol-file'. > +mi_gdb_test "-interpreter-exec console \"remove-symbol-file -a addr\"" \ > + ".*\\^done"\ > + "remove-symbol-file test" > + > +# Check var_count varobj changelist is not empty. > +mi_varobj_update var_count {var_count} "Update var_count" > > + mi_gdb_exit > + return 0 > mi_gdb_exit > return 0 > diff --git a/gdb/testsuite/gdb.mi/sym-file-lib.c b/gdb/testsuite/gdb.mi/sym-file-lib.c > new file mode 100644 > index 0000000..86c719c > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/sym-file-lib.c > @@ -0,0 +1,28 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2019 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +extern int > +bar () > +{ > + return 1; /* gdb break at bar. */ > +} > + > +extern int > +foo (int a) > +{ > + return a; /* gdb break at foo. */ > +} > diff --git a/gdb/testsuite/gdb.mi/sym-file-loader.c b/gdb/testsuite/gdb.mi/sym-file-loader.c > new file mode 100644 > index 0000000..0a3cd32 > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/sym-file-loader.c > @@ -0,0 +1,355 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2019 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "sym-file-loader.h" > + > +#ifdef TARGET_LP64 > + > +uint8_t > +elf_st_type (uint8_t st_info) > +{ > + return ELF64_ST_TYPE (st_info); > +} > + > +#elif defined TARGET_ILP32 > + > +uint8_t > +elf_st_type (uint8_t st_info) > +{ > + return ELF32_ST_TYPE (st_info); > +} > + > +#endif > + > +/* Load a program segment. */ > + > +static struct segment * > +load (uint8_t *addr, Elf_External_Phdr *phdr, struct segment *tail_seg) > +{ > + struct segment *seg = NULL; > + uint8_t *mapped_addr = NULL; > + void *from = NULL; > + void *to = NULL; > + > + /* For the sake of simplicity all operations are permitted. */ > + unsigned perm = PROT_READ | PROT_WRITE | PROT_EXEC; > + > + mapped_addr = (uint8_t *) mmap ((void *) GETADDR (phdr, p_vaddr), > + GET (phdr, p_memsz), perm, > + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); > + > + from = (void *) (addr + GET (phdr, p_offset)); > + to = (void *) mapped_addr; > + > + memcpy (to, from, GET (phdr, p_filesz)); > + > + seg = (struct segment *) malloc (sizeof (struct segment)); > + > + if (seg == 0) > + return 0; > + > + seg->mapped_addr = mapped_addr; > + seg->phdr = phdr; > + seg->next = 0; > + > + if (tail_seg != 0) > + tail_seg->next = seg; > + > + return seg; > +} > + > +/* Mini shared library loader. No reallocation > + is performed for the sake of simplicity. */ > + > +int > +load_shlib (const char *file, Elf_External_Ehdr **ehdr_out, > + struct segment **seg_out) > +{ > + uint64_t i; > + int fd; > + off_t fsize; > + uint8_t *addr; > + Elf_External_Ehdr *ehdr; > + Elf_External_Phdr *phdr; > + struct segment *head_seg = NULL; > + struct segment *tail_seg = NULL; > + > + /* Map the lib in memory for reading. */ > + fd = open (file, O_RDONLY); > + if (fd < 0) > + { > + perror ("fopen failed."); > + return -1; > + } > + > + fsize = lseek (fd, 0, SEEK_END); > + > + if (fsize < 0) > + { > + perror ("lseek failed."); > + return -1; > + } > + > + addr = (uint8_t *) mmap (NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0); > + if (addr == (uint8_t *) -1) > + { > + perror ("mmap failed."); > + return -1; > + } > + > + /* Check if the lib is an ELF file. */ > + ehdr = (Elf_External_Ehdr *) addr; > + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 > + || ehdr->e_ident[EI_MAG1] != ELFMAG1 > + || ehdr->e_ident[EI_MAG2] != ELFMAG2 > + || ehdr->e_ident[EI_MAG3] != ELFMAG3) > + { > + printf ("Not an ELF file: %x\n", ehdr->e_ident[EI_MAG0]); > + return -1; > + } > + > + if (ehdr->e_ident[EI_CLASS] == ELFCLASS32) > + { > + if (sizeof (void *) != 4) > + { > + printf ("Architecture mismatch."); > + return -1; > + } > + } > + else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) > + { > + if (sizeof (void *) != 8) > + { > + printf ("Architecture mismatch."); > + return -1; > + } > + } > + > + /* Load the program segments. For the sake of simplicity > + assume that no reallocation is needed. */ > + phdr = (Elf_External_Phdr *) (addr + GET (ehdr, e_phoff)); > + for (i = 0; i < GET (ehdr, e_phnum); i++, phdr++) > + { > + if (GET (phdr, p_type) == PT_LOAD) > + { > + struct segment *next_seg = load (addr, phdr, tail_seg); > + if (next_seg == 0) > + continue; > + tail_seg = next_seg; > + if (head_seg == 0) > + head_seg = next_seg; > + } > + } > + *ehdr_out = ehdr; > + *seg_out = head_seg; > + return 0; > +} > + > +/* Return the section-header table. */ > + > +Elf_External_Shdr * > +find_shdrtab (Elf_External_Ehdr *ehdr) > +{ > + return (Elf_External_Shdr *) (((uint8_t *) ehdr) + GET (ehdr, e_shoff)); > +} > + > +/* Return the string table of the section headers. */ > + > +const char * > +find_shstrtab (Elf_External_Ehdr *ehdr, uint64_t *size) > +{ > + const Elf_External_Shdr *shdr; > + const Elf_External_Shdr *shstr; > + > + if (GET (ehdr, e_shnum) <= GET (ehdr, e_shstrndx)) > + { > + printf ("The index of the string table is corrupt."); > + return NULL; > + } > + > + shdr = find_shdrtab (ehdr); > + > + shstr = &shdr[GET (ehdr, e_shstrndx)]; > + *size = GET (shstr, sh_size); > + return ((const char *) ehdr) + GET (shstr, sh_offset); > +} > + > +/* Return the string table named SECTION. */ > + > +const char * > +find_strtab (Elf_External_Ehdr *ehdr, > + const char *section, uint64_t *strtab_size) > +{ > + uint64_t shstrtab_size = 0; > + const char *shstrtab; > + uint64_t i; > + const Elf_External_Shdr *shdr = find_shdrtab (ehdr); > + > + /* Get the string table of the section headers. */ > + shstrtab = find_shstrtab (ehdr, &shstrtab_size); > + if (shstrtab == NULL) > + return NULL; > + > + for (i = 0; i < GET (ehdr, e_shnum); i++) > + { > + uint64_t name = GET (shdr + i, sh_name); > + if (GET (shdr + i, sh_type) == SHT_STRTAB && name <= shstrtab_size > + && strcmp ((const char *) &shstrtab[name], section) == 0) > + { > + *strtab_size = GET (shdr + i, sh_size); > + return ((const char *) ehdr) + GET (shdr + i, sh_offset); > + } > + > + } > + return NULL; > +} > + > +/* Return the section header named SECTION. */ > + > +Elf_External_Shdr * > +find_shdr (Elf_External_Ehdr *ehdr, const char *section) > +{ > + uint64_t shstrtab_size = 0; > + const char *shstrtab; > + uint64_t i; > + > + /* Get the string table of the section headers. */ > + shstrtab = find_shstrtab (ehdr, &shstrtab_size); > + if (shstrtab == NULL) > + return NULL; > + > + Elf_External_Shdr *shdr = find_shdrtab (ehdr); > + for (i = 0; i < GET (ehdr, e_shnum); i++) > + { > + uint64_t name = GET (shdr + i, sh_name); > + if (name <= shstrtab_size) > + { > + if (strcmp ((const char *) &shstrtab[name], section) == 0) > + return &shdr[i]; > + } > + > + } > + return NULL; > +} > + > +/* Return the symbol table. */ > + > +Elf_External_Sym * > +find_symtab (Elf_External_Ehdr *ehdr, uint64_t *symtab_size) > +{ > + uint64_t i; > + const Elf_External_Shdr *shdr = find_shdrtab (ehdr); > + > + for (i = 0; i < GET (ehdr, e_shnum); i++) > + { > + if (GET (shdr + i, sh_type) == SHT_SYMTAB) > + { > + *symtab_size = GET (shdr + i, sh_size) / sizeof (Elf_External_Sym); > + return (Elf_External_Sym *) (((const char *) ehdr) + > + GET (shdr + i, sh_offset)); > + } > + } > + return NULL; > +} > + > +/* Translate a file offset to an address in a loaded segment. */ > + > +int > +translate_offset (uint64_t file_offset, struct segment *seg, void **addr) > +{ > + while (seg) > + { > + uint64_t p_from, p_to; > + > + Elf_External_Phdr *phdr = seg->phdr; > + > + if (phdr == NULL) > + { > + seg = seg->next; > + continue; > + } > + > + p_from = GET (phdr, p_offset); > + p_to = p_from + GET (phdr, p_filesz); > + > + if (p_from <= file_offset && file_offset < p_to) > + { > + *addr = (void *) (seg->mapped_addr + (file_offset - p_from)); > + return 0; > + } > + seg = seg->next; > + } > + > + return -1; > +} > + > +/* Lookup the address of FUNC. */ > + > +int > +lookup_function (const char *func, > + Elf_External_Ehdr *ehdr, struct segment *seg, void **addr) > +{ > + const char *strtab; > + uint64_t strtab_size = 0; > + Elf_External_Sym *symtab; > + uint64_t symtab_size = 0; > + uint64_t i; > + > + /* Get the string table for the symbols. */ > + strtab = find_strtab (ehdr, ".strtab", &strtab_size); > + if (strtab == NULL) > + { > + printf (".strtab not found."); > + return -1; > + } > + > + /* Get the symbol table. */ > + symtab = find_symtab (ehdr, &symtab_size); > + if (symtab == NULL) > + { > + printf ("symbol table not found."); > + return -1; > + } > + > + for (i = 0; i < symtab_size; i++) > + { > + Elf_External_Sym *sym = &symtab[i]; > + > + if (elf_st_type (GET (sym, st_info)) != STT_FUNC) > + continue; > + > + if (GET (sym, st_name) < strtab_size) > + { > + const char *name = &strtab[GET (sym, st_name)]; > + if (strcmp (name, func) == 0) > + { > + > + uint64_t offset = GET (sym, st_value); > + return translate_offset (offset, seg, addr); > + } > + } > + } > + > + return -1; > +} > diff --git a/gdb/testsuite/gdb.mi/sym-file-loader.h b/gdb/testsuite/gdb.mi/sym-file-loader.h > new file mode 100644 > index 0000000..d6ebb39 > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/sym-file-loader.h > @@ -0,0 +1,101 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2019 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef __SYM_FILE_LOADER__ > +#define __SYM_FILE_LOADER__ > + > +#include > +#include > +#include > +#include > + > +#ifdef TARGET_LP64 > + > +typedef Elf64_External_Phdr Elf_External_Phdr; > +typedef Elf64_External_Ehdr Elf_External_Ehdr; > +typedef Elf64_External_Shdr Elf_External_Shdr; > +typedef Elf64_External_Sym Elf_External_Sym; > +typedef uint64_t Elf_Addr; > + > +#elif defined TARGET_ILP32 > + > +typedef Elf32_External_Phdr Elf_External_Phdr; > +typedef Elf32_External_Ehdr Elf_External_Ehdr; > +typedef Elf32_External_Shdr Elf_External_Shdr; > +typedef Elf32_External_Sym Elf_External_Sym; > +typedef uint32_t Elf_Addr; > + > +#endif > + > +#define GET(hdr, field) (\ > +sizeof ((hdr)->field) == 1 ? (uint64_t) (hdr)->field[0] : \ > +sizeof ((hdr)->field) == 2 ? (uint64_t) *(uint16_t *) (hdr)->field : \ > +sizeof ((hdr)->field) == 4 ? (uint64_t) *(uint32_t *) (hdr)->field : \ > +sizeof ((hdr)->field) == 8 ? *(uint64_t *) (hdr)->field : \ > +*(uint64_t *) NULL) > + > +#define GETADDR(hdr, field) (\ > +sizeof ((hdr)->field) == sizeof (Elf_Addr) ? *(Elf_Addr *) (hdr)->field : \ > +*(Elf_Addr *) NULL) > + > +struct segment > +{ > + uint8_t *mapped_addr; > + Elf_External_Phdr *phdr; > + struct segment *next; > +}; > + > +/* Mini shared library loader. No reallocation is performed > + for the sake of simplicity. */ > + > +int > +load_shlib (const char *file, Elf_External_Ehdr **ehdr_out, > + struct segment **seg_out); > + > +/* Return the section-header table. */ > + > +Elf_External_Shdr *find_shdrtab (Elf_External_Ehdr *ehdr); > + > +/* Return the string table of the section headers. */ > + > +const char *find_shstrtab (Elf_External_Ehdr *ehdr, uint64_t *size); > + > +/* Return the string table named SECTION. */ > + > +const char *find_strtab (Elf_External_Ehdr *ehdr, > + const char *section, uint64_t *strtab_size); > + > +/* Return the section header named SECTION. */ > + > +Elf_External_Shdr *find_shdr (Elf_External_Ehdr *ehdr, const char *section); > + > +/* Return the symbol table. */ > + > +Elf_External_Sym *find_symtab (Elf_External_Ehdr *ehdr, > + uint64_t *symtab_size); > + > +/* Translate a file offset to an address in a loaded segment. */ > + > +int translate_offset (uint64_t file_offset, struct segment *seg, void **addr); > + > +/* Lookup the address of FUNC. */ > + > +int > +lookup_function (const char *func, Elf_External_Ehdr* ehdr, > + struct segment *seg, void **addr); > + > +#endif > diff --git a/gdb/testsuite/gdb.mi/sym-file-main.c b/gdb/testsuite/gdb.mi/sym-file-main.c > new file mode 100644 > index 0000000..ecdef4e > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/sym-file-main.c > @@ -0,0 +1,86 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2019 Free Software Foundation, Inc. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#include > +#include > + > +#include "sym-file-loader.h" > + > +// Global variable > +int count = 0; > + > +void > +gdb_add_symbol_file (void *addr, const char *file) > +{ > + return; > +} > + > +void > +gdb_remove_symbol_file (void *addr) > +{ > + return; > +} > + > +/* Load a shared library without relying on the standard > + loader to test GDB's commands for adding and removing > + symbol files at runtime. */ > + > +int > +main (int argc, const char *argv[]) > +{ > + const char *file = SHLIB_NAME; > + Elf_External_Ehdr *ehdr = NULL; > + struct segment *head_seg = NULL; > + Elf_External_Shdr *text; > + char *text_addr = NULL; > + int (*pbar) () = NULL; > + int (*pfoo) (int) = NULL; > + > + if (load_shlib (file, &ehdr, &head_seg) != 0) > + return -1; > + > + /* Get the text section. */ > + text = find_shdr (ehdr, ".text"); > + if (text == NULL) > + return -1; > + > + /* Notify GDB to add the symbol file. */ > + if (translate_offset (GET (text, sh_offset), head_seg, (void **) &text_addr) > + != 0) > + return -1; > + > + gdb_add_symbol_file (text_addr, file); > + > + /* Call bar from SHLIB_NAME. */ > + if (lookup_function ("bar", ehdr, head_seg, (void *) &pbar) != 0) > + return -1; > + > + (*pbar) (); > + > + /* Call foo from SHLIB_NAME. */ > + if (lookup_function ("foo", ehdr, head_seg, (void *) &pfoo) != 0) > + return -1; > + > + (*pfoo) (2); > + > + count++; > + > + /* Notify GDB to remove the symbol file. */ > + gdb_remove_symbol_file (text_addr); > + > + return 0; > +}