From patchwork Wed Apr 10 22:20:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 32255 Received: (qmail 40387 invoked by alias); 10 Apr 2019 22:21:08 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 40362 invoked by uid 89); 10 Apr 2019 22:21:08 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-20.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.1 spammy= X-HELO: mga07.intel.com From: "H.J. Lu" To: libc-alpha@sourceware.org Subject: [PATCH] x86: Avoid loading the second PT_NOTE segment Date: Wed, 10 Apr 2019 15:20:54 -0700 Message-Id: <20190410222054.1584-1-hjl.tools@gmail.com> MIME-Version: 1.0 On x86-64, there may be 2 PT_NOTE segments: NOTE 0x0000000000000350 0x0000000000000350 0x0000000000000350 0x0000000000000040 0x0000000000000040 R 0x8 NOTE 0x0000000000000390 0x0000000000000390 0x0000000000000390 0x0000000000000044 0x0000000000000044 R 0x4 ... 07 .note.gnu.property 08 .note.gnu.build-id .note.ABI-tag When loading a shared library, _dl_process_pt_note is called on each PT_NOTE segment. It will seek and load its content from disk. This patch avoids loading the second PT_NOTE segment when the GNU property note has been processed. For loading libc.so.6, before: lseek(3, 848, SEEK_SET) = 848 read(3, "\4\0\0\0000\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 64) = 64 lseek(3, 912, SEEK_SET) = 912 read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0Q,\254S$\377\225\242\324\372\253\303J\267\301D"..., 68) = 68 after: lseek(3, 848, SEEK_SET) = 848 read(3, "\4\0\0\0000\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 64) = 64 We avoid the extra: lseek(3, 912, SEEK_SET) = 912 read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0Q,\254S$\377\225\242\324\372\253\303J\267\301D"..., 68) = 68 * sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Don't check l_cet here. (_dl_process_pt_note): Skip if the GNU property note has been processed. (_rtld_process_pt_note): Likewise. --- sysdeps/x86/dl-prop.h | 59 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h index 1b335ccbb3..5e21ad5fec 100644 --- a/sysdeps/x86/dl-prop.h +++ b/sysdeps/x86/dl-prop.h @@ -49,10 +49,6 @@ _dl_process_cet_property_note (struct link_map *l, const ElfW(Addr) align) { #if CET_ENABLED - /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */ - if (l->l_cet != lc_unknown) - return; - /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in 32-bit objects and to 8 bytes in 64-bit objects. Skip notes with incorrect alignment. */ @@ -152,33 +148,36 @@ _dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph, int fd, struct filebuf *fbp) { # if CET_ENABLED - const ElfW(Nhdr) *note; - ElfW(Nhdr) *note_malloced = NULL; - ElfW(Addr) size = ph->p_filesz; - - if (ph->p_offset + size <= (size_t) fbp->len) - note = (const void *) (fbp->buf + ph->p_offset); - else + if (l->l_cet == lc_unknown) { - if (size < __MAX_ALLOCA_CUTOFF) - note = alloca (size); + const ElfW(Nhdr) *note; + ElfW(Nhdr) *note_malloced = NULL; + ElfW(Addr) size = ph->p_filesz; + + if (ph->p_offset + size <= (size_t) fbp->len) + note = (const void *) (fbp->buf + ph->p_offset); else { - note_malloced = malloc (size); - note = note_malloced; - } - __lseek (fd, ph->p_offset, SEEK_SET); - if (__read_nocancel (fd, (void *) note, size) != size) - { - if (note_malloced) - free (note_malloced); - return -1; + if (size < __MAX_ALLOCA_CUTOFF) + note = alloca (size); + else + { + note_malloced = malloc (size); + note = note_malloced; + } + __lseek (fd, ph->p_offset, SEEK_SET); + if (__read_nocancel (fd, (void *) note, size) != size) + { + if (note_malloced) + free (note_malloced); + return -1; + } } - } - _dl_process_cet_property_note (l, note, size, ph->p_align); - if (note_malloced) - free (note_malloced); + _dl_process_cet_property_note (l, note, size, ph->p_align); + if (note_malloced) + free (note_malloced); + } # endif return 0; } @@ -187,8 +186,12 @@ _dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph, static inline int __attribute__ ((unused)) _rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph) { - const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr); - _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align); + /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */ + if (l->l_cet == lc_unknown) + { + const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr); + _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align); + } return 0; }