From patchwork Tue Aug 26 21:38:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Doug Evans X-Patchwork-Id: 2545 Received: (qmail 23482 invoked by alias); 26 Aug 2014 21:38:48 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 23469 invoked by uid 89); 26 Aug 2014 21:38:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-yh0-f74.google.com Received: from mail-yh0-f74.google.com (HELO mail-yh0-f74.google.com) (209.85.213.74) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 26 Aug 2014 21:38:44 +0000 Received: by mail-yh0-f74.google.com with SMTP id 29so1821263yhl.1 for ; Tue, 26 Aug 2014 14:38:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-type:content-transfer-encoding; bh=MgkyyuImU/7furyHK6+A4TQr/28AdTkD36VYzTAbp/A=; b=mL+Do2pEH7IYwL/vkaPn0eELJ/3sZgSg0YJXW9ScEs1Uf57nXc18x/8qH4cQlIUjoh CAgVdTPYjM/NqDJ4VF3UcN5DdWGC6Fxb/PI9mk13q0HVzsmL4G8Uk4apSTrhBROwrGTt zswAhkjCeMphUOAMs3Y5+I6MX0059byqFyR1/E2xftCkVzdTyS7whzu7jqSMppvbGCSd RtQy2ZzKvl+N5d5nk38DSRPD4mGvAghSJ/DEu2e5u+6p2bkyafEQE0w0ffjHiKauHfUc 8mD3wEx1EYbzB0x707rPC0DoNFEhKGnAp5GjVxAKkeq7ve82FGaZ/xdS/gTUHUXCVF3z Jzzg== X-Gm-Message-State: ALoCoQlt/i5pcmFAoHMfU8HgIKLW/ORF38AO/ZS7vQan3tFzxKB/rf/UIRvGhqGvvwtC6pAJZNG6J0Kx8lGTt3XY9Z+XbT0d+hK1My4/y+1j2M+uJ7SYlDPtAEWb/SOzbQN2/dyCCdGB X-Received: by 10.236.63.67 with SMTP id z43mr6639089yhc.11.1409089122524; Tue, 26 Aug 2014 14:38:42 -0700 (PDT) Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) by gmr-mx.google.com with ESMTPS id j25si299237yhb.0.2014.08.26.14.38.42 for (version=TLSv1.1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 26 Aug 2014 14:38:42 -0700 (PDT) Received: from ruffy.mtv.corp.google.com (ruffy.mtv.corp.google.com [172.17.128.44]) by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTPS id 0ED355A43A8 for ; Tue, 26 Aug 2014 14:38:41 -0700 (PDT) From: Doug Evans To: gdb-patches@sourceware.org Subject: [PATCH 2/2] symtab.c cleanup Date: Tue, 26 Aug 2014 14:38:41 -0700 Message-ID: MIME-Version: 1.0 X-IsSubscribed: yes Hi. This is the second of two patches mentioned here: https://sourceware.org/ml/gdb-patches/2014-08/msg00535.html There is a convention that Ctrl-L marks major sections of source files. I use emacs so I kinda like it ... Anyways, in_prologue and skip_prologue_using_sal are clearly in the wrong section (completion support). This patch moves them to a much better location, next to other prologue-related functions. 2014-08-26 Doug Evans * symtab.c (in_prologue): Move definition to better spot. (skip_prologue_using_sal): Ditto. diff --git a/gdb/symtab.c b/gdb/symtab.c index ab56892..c530d50 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3034,6 +3034,193 @@ skip_prologue_sal (struct symtab_and_line *sal) } } +/* Determine if PC is in the prologue of a function. The prologue is the area + between the first instruction of a function, and the first executable line. + Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. + + If non-zero, func_start is where we think the prologue starts, possibly + by previous examination of symbol table information. */ + +int +in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) +{ + struct symtab_and_line sal; + CORE_ADDR func_addr, func_end; + + /* We have several sources of information we can consult to figure + this out. + - Compilers usually emit line number info that marks the prologue + as its own "source line". So the ending address of that "line" + is the end of the prologue. If available, this is the most + reliable method. + - The minimal symbols and partial symbols, which can usually tell + us the starting and ending addresses of a function. + - If we know the function's start address, we can call the + architecture-defined gdbarch_skip_prologue function to analyze the + instruction stream and guess where the prologue ends. + - Our `func_start' argument; if non-zero, this is the caller's + best guess as to the function's entry point. At the time of + this writing, handle_inferior_event doesn't get this right, so + it should be our last resort. */ + + /* Consult the partial symbol table, to find which function + the PC is in. */ + if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + CORE_ADDR prologue_end; + + /* We don't even have minsym information, so fall back to using + func_start, if given. */ + if (! func_start) + return 1; /* We *might* be in a prologue. */ + + prologue_end = gdbarch_skip_prologue (gdbarch, func_start); + + return func_start <= pc && pc < prologue_end; + } + + /* If we have line number information for the function, that's + usually pretty reliable. */ + sal = find_pc_line (func_addr, 0); + + /* Now sal describes the source line at the function's entry point, + which (by convention) is the prologue. The end of that "line", + sal.end, is the end of the prologue. + + Note that, for functions whose source code is all on a single + line, the line number information doesn't always end up this way. + So we must verify that our purported end-of-prologue address is + *within* the function, not at its start or end. */ + if (sal.line == 0 + || sal.end <= func_addr + || func_end <= sal.end) + { + /* We don't have any good line number info, so use the minsym + information, together with the architecture-specific prologue + scanning code. */ + CORE_ADDR prologue_end = gdbarch_skip_prologue (gdbarch, func_addr); + + return func_addr <= pc && pc < prologue_end; + } + + /* We have line number info, and it looks good. */ + return func_addr <= pc && pc < sal.end; +} + +/* Given PC at the function's start address, attempt to find the + prologue end using SAL information. Return zero if the skip fails. + + A non-optimized prologue traditionally has one SAL for the function + and a second for the function body. A single line function has + them both pointing at the same line. + + An optimized prologue is similar but the prologue may contain + instructions (SALs) from the instruction body. Need to skip those + while not getting into the function body. + + The functions end point and an increasing SAL line are used as + indicators of the prologue's endpoint. + + This code is based on the function refine_prologue_limit + (found in ia64). */ + +CORE_ADDR +skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) +{ + struct symtab_and_line prologue_sal; + CORE_ADDR start_pc; + CORE_ADDR end_pc; + const struct block *bl; + + /* Get an initial range for the function. */ + find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc); + start_pc += gdbarch_deprecated_function_start_offset (gdbarch); + + prologue_sal = find_pc_line (start_pc, 0); + if (prologue_sal.line != 0) + { + /* For languages other than assembly, treat two consecutive line + entries at the same address as a zero-instruction prologue. + The GNU assembler emits separate line notes for each instruction + in a multi-instruction macro, but compilers generally will not + do this. */ + if (prologue_sal.symtab->language != language_asm) + { + struct linetable *linetable = LINETABLE (prologue_sal.symtab); + int idx = 0; + + /* Skip any earlier lines, and any end-of-sequence marker + from a previous function. */ + while (linetable->item[idx].pc != prologue_sal.pc + || linetable->item[idx].line == 0) + idx++; + + if (idx+1 < linetable->nitems + && linetable->item[idx+1].line != 0 + && linetable->item[idx+1].pc == start_pc) + return start_pc; + } + + /* If there is only one sal that covers the entire function, + then it is probably a single line function, like + "foo(){}". */ + if (prologue_sal.end >= end_pc) + return 0; + + while (prologue_sal.end < end_pc) + { + struct symtab_and_line sal; + + sal = find_pc_line (prologue_sal.end, 0); + if (sal.line == 0) + break; + /* Assume that a consecutive SAL for the same (or larger) + line mark the prologue -> body transition. */ + if (sal.line >= prologue_sal.line) + break; + /* Likewise if we are in a different symtab altogether + (e.g. within a file included via #include).  */ + if (sal.symtab != prologue_sal.symtab) + break; + + /* The line number is smaller. Check that it's from the + same function, not something inlined. If it's inlined, + then there is no point comparing the line numbers. */ + bl = block_for_pc (prologue_sal.end); + while (bl) + { + if (block_inlined_p (bl)) + break; + if (BLOCK_FUNCTION (bl)) + { + bl = NULL; + break; + } + bl = BLOCK_SUPERBLOCK (bl); + } + if (bl != NULL) + break; + + /* The case in which compiler's optimizer/scheduler has + moved instructions into the prologue. We look ahead in + the function looking for address ranges whose + corresponding line number is less the first one that we + found for the function. This is more conservative then + refine_prologue_limit which scans a large number of SALs + looking for any in the prologue. */ + prologue_sal = sal; + } + } + + if (prologue_sal.end < end_pc) + /* Return the end of this line, or zero if we could not find a + line. */ + return prologue_sal.end; + else + /* Don't return END_PC, which is past the end of the function. */ + return prologue_sal.pc; +} + /* If P is of the form "operator[ \t]+..." where `...' is some legitimate operator text, return a pointer to the beginning of the substring of the operator text. @@ -4827,193 +5014,6 @@ make_source_files_completion_list (const char *text, const char *word) return list; } - -/* Determine if PC is in the prologue of a function. The prologue is the area - between the first instruction of a function, and the first executable line. - Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. - - If non-zero, func_start is where we think the prologue starts, possibly - by previous examination of symbol table information. */ - -int -in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) -{ - struct symtab_and_line sal; - CORE_ADDR func_addr, func_end; - - /* We have several sources of information we can consult to figure - this out. - - Compilers usually emit line number info that marks the prologue - as its own "source line". So the ending address of that "line" - is the end of the prologue. If available, this is the most - reliable method. - - The minimal symbols and partial symbols, which can usually tell - us the starting and ending addresses of a function. - - If we know the function's start address, we can call the - architecture-defined gdbarch_skip_prologue function to analyze the - instruction stream and guess where the prologue ends. - - Our `func_start' argument; if non-zero, this is the caller's - best guess as to the function's entry point. At the time of - this writing, handle_inferior_event doesn't get this right, so - it should be our last resort. */ - - /* Consult the partial symbol table, to find which function - the PC is in. */ - if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end)) - { - CORE_ADDR prologue_end; - - /* We don't even have minsym information, so fall back to using - func_start, if given. */ - if (! func_start) - return 1; /* We *might* be in a prologue. */ - - prologue_end = gdbarch_skip_prologue (gdbarch, func_start); - - return func_start <= pc && pc < prologue_end; - } - - /* If we have line number information for the function, that's - usually pretty reliable. */ - sal = find_pc_line (func_addr, 0); - - /* Now sal describes the source line at the function's entry point, - which (by convention) is the prologue. The end of that "line", - sal.end, is the end of the prologue. - - Note that, for functions whose source code is all on a single - line, the line number information doesn't always end up this way. - So we must verify that our purported end-of-prologue address is - *within* the function, not at its start or end. */ - if (sal.line == 0 - || sal.end <= func_addr - || func_end <= sal.end) - { - /* We don't have any good line number info, so use the minsym - information, together with the architecture-specific prologue - scanning code. */ - CORE_ADDR prologue_end = gdbarch_skip_prologue (gdbarch, func_addr); - - return func_addr <= pc && pc < prologue_end; - } - - /* We have line number info, and it looks good. */ - return func_addr <= pc && pc < sal.end; -} - -/* Given PC at the function's start address, attempt to find the - prologue end using SAL information. Return zero if the skip fails. - - A non-optimized prologue traditionally has one SAL for the function - and a second for the function body. A single line function has - them both pointing at the same line. - - An optimized prologue is similar but the prologue may contain - instructions (SALs) from the instruction body. Need to skip those - while not getting into the function body. - - The functions end point and an increasing SAL line are used as - indicators of the prologue's endpoint. - - This code is based on the function refine_prologue_limit - (found in ia64). */ - -CORE_ADDR -skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) -{ - struct symtab_and_line prologue_sal; - CORE_ADDR start_pc; - CORE_ADDR end_pc; - const struct block *bl; - - /* Get an initial range for the function. */ - find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc); - start_pc += gdbarch_deprecated_function_start_offset (gdbarch); - - prologue_sal = find_pc_line (start_pc, 0); - if (prologue_sal.line != 0) - { - /* For languages other than assembly, treat two consecutive line - entries at the same address as a zero-instruction prologue. - The GNU assembler emits separate line notes for each instruction - in a multi-instruction macro, but compilers generally will not - do this. */ - if (prologue_sal.symtab->language != language_asm) - { - struct linetable *linetable = LINETABLE (prologue_sal.symtab); - int idx = 0; - - /* Skip any earlier lines, and any end-of-sequence marker - from a previous function. */ - while (linetable->item[idx].pc != prologue_sal.pc - || linetable->item[idx].line == 0) - idx++; - - if (idx+1 < linetable->nitems - && linetable->item[idx+1].line != 0 - && linetable->item[idx+1].pc == start_pc) - return start_pc; - } - - /* If there is only one sal that covers the entire function, - then it is probably a single line function, like - "foo(){}". */ - if (prologue_sal.end >= end_pc) - return 0; - - while (prologue_sal.end < end_pc) - { - struct symtab_and_line sal; - - sal = find_pc_line (prologue_sal.end, 0); - if (sal.line == 0) - break; - /* Assume that a consecutive SAL for the same (or larger) - line mark the prologue -> body transition. */ - if (sal.line >= prologue_sal.line) - break; - /* Likewise if we are in a different symtab altogether - (e.g. within a file included via #include).  */ - if (sal.symtab != prologue_sal.symtab) - break; - - /* The line number is smaller. Check that it's from the - same function, not something inlined. If it's inlined, - then there is no point comparing the line numbers. */ - bl = block_for_pc (prologue_sal.end); - while (bl) - { - if (block_inlined_p (bl)) - break; - if (BLOCK_FUNCTION (bl)) - { - bl = NULL; - break; - } - bl = BLOCK_SUPERBLOCK (bl); - } - if (bl != NULL) - break; - - /* The case in which compiler's optimizer/scheduler has - moved instructions into the prologue. We look ahead in - the function looking for address ranges whose - corresponding line number is less the first one that we - found for the function. This is more conservative then - refine_prologue_limit which scans a large number of SALs - looking for any in the prologue. */ - prologue_sal = sal; - } - } - - if (prologue_sal.end < end_pc) - /* Return the end of this line, or zero if we could not find a - line. */ - return prologue_sal.end; - else - /* Don't return END_PC, which is past the end of the function. */ - return prologue_sal.pc; -} /* Track MAIN */