From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 2E3D53858439 for ; Tue, 19 Jul 2022 14:21:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2E3D53858439 Received: from mail-lf1-f72.google.com (mail-lf1-f72.google.com [209.85.167.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-561-nOdeMDPMNb6wJhyaX3OzHQ-1; Tue, 19 Jul 2022 10:21:35 -0400 X-MC-Unique: nOdeMDPMNb6wJhyaX3OzHQ-1 Received: by mail-lf1-f72.google.com with SMTP id z1-20020a195041000000b00489cc321e11so5525495lfj.23 for ; Tue, 19 Jul 2022 07:21:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=/+xwl7wseJxtZaAPwUlm8ll11oO9ZbtsH5RkWS7dH/c=; b=riFwcSppMKa0ftk0+Gc4RTPB/ZLIdKyvZ8Xc6VydCWelpkbO5DNj195wEI1GqIIRbM HSyGIgW3Sr8AAcQQahOERr2MDtVIJ4wHaTJ8Pfqcat2gQ+Y0ZuKraLQnD5XJutULVxgA +cEiTItgodu3CAirVWxnAr1b8r7r/PH0x9luX58YDf8pDGPrQYpjrsB60CV3ALj/8rXK QPgRAawK4z+Eevl03jtC8Ts6CkkvnkDwhEqMDHaaBPba71gcFfsd2/cBhy85DYCbAJ2A V4ry0jOKDQRkz5vNMsIhDRT0N7uq+oz7H2ADTNUUBPlEoV9haFNp66VoTu4M/9EZ9VmE Y6HA== X-Gm-Message-State: AJIora+eoFkwzwMcdoL52Iz7V83uKA+bke1505e3/pV3OjuR5+FT52J4 dGQk7n9iGR00Vq/ZgpgncdR8u7zSokKJfHqpSjhlwQiBIcX2d+eHE7lmQkKxLtSXi+5ckzLmCX7 i6TJ4zDzD+hK5e5CumOnDGO3HwcYDGQ/rn4GRySCbnA== X-Received: by 2002:a05:651c:211e:b0:25d:9fc1:76e0 with SMTP id a30-20020a05651c211e00b0025d9fc176e0mr11174163ljq.531.1658240493344; Tue, 19 Jul 2022 07:21:33 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tMFoSbPTETZZEFXMTPQWEkCvzGTMi8X4ezXX8S8+D2kI3VUU0OpkUiD+IC1mkqSzFdNVgSeQ9imcb9p0uIpAM= X-Received: by 2002:a05:651c:211e:b0:25d:9fc1:76e0 with SMTP id a30-20020a05651c211e00b0025d9fc176e0mr11174150ljq.531.1658240493018; Tue, 19 Jul 2022 07:21:33 -0700 (PDT) MIME-Version: 1.0 From: Di Chen Date: Tue, 19 Jul 2022 22:21:21 +0800 Message-ID: Subject: [PATCH v2] libdw/libdwfl: Add API for accessing registers To: elfutils-devel@sourceware.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Elfutils-devel mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Jul 2022 14:21:39 -0000 >From 9c25b08e46c2031b569a85f91713d009b83f4c26 Mon Sep 17 00:00:00 2001 From: Di Chen Date: Tue, 19 Jul 2022 14:54:45 +0800 Subject: [PATCH] libdw/libdwfl: Add API for accessing registers Dwfl has most of the infrastructure to keep the full unwind state, including the state of unwound registers per frame using Dwfl_Thread_Callbacks. But there is no public API to access the state, except for the PC (dwfl_frame_pc). This update renames previous state_get_reg() (in libdwfl/frame_unwind.c) to dwfl_frame_reg(), adds a regno check, and makes it a public API. Signed-off-by: Di Chen --- libdw/libdw.map | 1 + libdwfl/dwfl_frame_regs.c | 18 ++++++++++++++++++ libdwfl/frame_unwind.c | 21 +++++---------------- libdwfl/libdwfl.h | 4 ++++ libdwfl/libdwflP.h | 2 ++ 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/libdw/libdw.map b/libdw/libdw.map index 6da25561..8f393438 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -370,4 +370,5 @@ ELFUTILS_0.186 { ELFUTILS_0.188 { global: dwfl_get_debuginfod_client; + dwfl_frame_reg; } ELFUTILS_0.186; diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c index 83b1abef..92c4a692 100644 --- a/libdwfl/dwfl_frame_regs.c +++ b/libdwfl/dwfl_frame_regs.c @@ -59,3 +59,21 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) state->pc_state = DWFL_FRAME_STATE_PC_SET; } INTDEF(dwfl_thread_state_register_pc) + +bool +dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val) +{ + if ((state->regs_set[regno / sizeof (*state->regs_set) / 8] + & ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0) + { + __libdwfl_seterrno (DWFL_E_INVALID_REGNO); + return false; + } + if (! __libdwfl_frame_reg_get (state, regno, val)) + { + __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); + return false; + } + return true; +} +INTDEF(dwfl_frame_reg) diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c index 9ac33833..38f5b332 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -78,17 +78,6 @@ __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) return true; } -static bool -state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) -{ - if (! __libdwfl_frame_reg_get (state, regno, val)) - { - __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); - return false; - } - return true; -} - static int bra_compar (const void *key_voidp, const void *elem_voidp) { @@ -211,7 +200,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, } break; case DW_OP_reg0 ... DW_OP_reg31: - if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1) + if (! dwfl_frame_reg (state, op->atom - DW_OP_reg0, &val1) || ! push (val1)) { free (stack.addrs); @@ -219,14 +208,14 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, } break; case DW_OP_regx: - if (! state_get_reg (state, op->number, &val1) || ! push (val1)) + if (! dwfl_frame_reg (state, op->number, &val1) || ! push (val1)) { free (stack.addrs); return false; } break; case DW_OP_breg0 ... DW_OP_breg31: - if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1)) + if (! dwfl_frame_reg (state, op->atom - DW_OP_breg0, &val1)) { free (stack.addrs); return false; @@ -239,7 +228,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, } break; case DW_OP_bregx: - if (! state_get_reg (state, op->number, &val1)) + if (! dwfl_frame_reg (state, op->number, &val1)) { free (stack.addrs); return false; @@ -591,7 +580,7 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) else if (reg_ops == NULL) { /* REGNO is same-value. */ - if (! state_get_reg (state, regno, ®val)) + if (! dwfl_frame_reg (state, regno, ®val)) continue; } else diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index b323e8fb..aba75afe 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -798,6 +798,10 @@ int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid, bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) __nonnull_attribute__ (1, 2); +/* Return *val (register value) for frame STATE. */ +bool dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val) + __nonnull_attribute__ (1); + /* Return the internal debuginfod-client connection handle for the DWFL session. When the client connection has not yet been initialized, it will be done on the first call to this function. If elfutils is compiled without support for debuginfod, diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 9f598370..a6d4396a 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -81,6 +81,7 @@ typedef struct Dwfl_Process Dwfl_Process; DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl")) \ DWFL_ERROR (CORE_MISSING, N_("Missing data in core file")) \ DWFL_ERROR (INVALID_REGISTER, N_("Invalid register")) \ + DWFL_ERROR (INVALID_REGNO, N_("Invalid register number")) \ DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory")) \ DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF")) \ DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem")) \ @@ -786,6 +787,7 @@ INTDECL (dwfl_getthread_frames) INTDECL (dwfl_getthreads) INTDECL (dwfl_thread_getframes) INTDECL (dwfl_frame_pc) +INTDECL (dwfl_frame_reg) INTDECL (dwfl_get_debuginfod_client) /* Leading arguments standard to callbacks passed a Dwfl_Module. */ -- 2.35.3