From: Kirill Radkin Date: Tue, 3 Jun 2025 13:48:23 +0000 (+0300) Subject: gdbserver: Update require_int function to parse offset for pread packet X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ba4bedeafa1cd9361b49a11dcd0e4eb0de6dadca;p=thirdparty%2Fbinutils-gdb.git gdbserver: Update require_int function to parse offset for pread packet Currently gdbserver uses the require_int() function to parse the requested offset (in vFile::pread packet and the like). This function allows integers up to 0x7fffffff (to fit in 32-bit int), however the offset (for the pread system call) has an off_t type which can be larger than 32-bit. This patch allows require_int() function to parse offset up to the maximum value implied by the off_t type. Approved-By: Pedro Alves Change-Id: I3691bcc1ab1838c0db7f8b82d297d276a5419c8c --- diff --git a/gdb/testsuite/gdb.server/pread-offset-size.S b/gdb/testsuite/gdb.server/pread-offset-size.S new file mode 100644 index 00000000000..6ca8cf08a08 --- /dev/null +++ b/gdb/testsuite/gdb.server/pread-offset-size.S @@ -0,0 +1,29 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 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 . */ + +/* Here we are trying to create a large binary (> 2 GB), + 3742415472 bytes is about 3.5 gigabytes. */ + + .text + .globl _start +_start: + .skip 3742415472 + ret + .globl f + .type f, @function +f: + ret diff --git a/gdb/testsuite/gdb.server/pread-offset-size.exp b/gdb/testsuite/gdb.server/pread-offset-size.exp new file mode 100644 index 00000000000..54e67c529f9 --- /dev/null +++ b/gdb/testsuite/gdb.server/pread-offset-size.exp @@ -0,0 +1,49 @@ +# Copyright (C) 2025 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 . +# +# Check that GDBserver's vFile::pread implementation is able to access +# large files (> 2GB). + +load_lib gdbserver-support.exp + +require allow_gdbserver_tests + +standard_testfile .S + +if { [prepare_for_testing ${testfile}.exp $testfile \ + $srcfile {debug additional_flags=-nostdlib} ] } { + return -1 +} + +clean_restart + +gdb_test_no_output "set remote exec-file $binfile" \ + "set remote exec-file" + +# Make sure we're disconnected, in case we're testing with an +# extended-remote board, therefore already connected. +gdb_test "disconnect" ".*" + +set res [gdbserver_spawn ""] +set gdbserver_protocol [lindex $res 0] +set gdbserver_gdbport [lindex $res 1] + +gdb_test "target $gdbserver_protocol $gdbserver_gdbport" \ + "Remote debugging using .*" \ + "target $gdbserver_protocol" + +# If loading the large binary was successful, we should be able to +# place a breakpoint on f. +gdb_test "break f" "Breakpoint 1.*" diff --git a/gdbserver/hostio.cc b/gdbserver/hostio.cc index ca8e4918e47..69729a83447 100644 --- a/gdbserver/hostio.cc +++ b/gdbserver/hostio.cc @@ -89,12 +89,18 @@ require_filename (char **pp, char *filename) return 0; } +template static int -require_int (char **pp, int *value) +require_int (char **pp, T *value) { + constexpr bool is_signed = std::is_signed::value; + char *p; int count, firstdigit; + /* Max count of hexadecimal digits in T (1 hex digit is 4 bits). */ + int max_count = sizeof (T) * CHAR_BIT / 4; + p = *pp; *value = 0; count = 0; @@ -111,7 +117,8 @@ require_int (char **pp, int *value) firstdigit = nib; /* Don't allow overflow. */ - if (count >= 8 || (count == 7 && firstdigit >= 0x8)) + if (count >= max_count + || (is_signed && count == (max_count - 1) && firstdigit >= 0x8)) return -1; *value = *value * 16 + nib; @@ -343,7 +350,8 @@ handle_open (char *own_buf) static void handle_pread (char *own_buf, int *new_packet_len) { - int fd, ret, len, offset, bytes_sent; + int fd, ret, len, bytes_sent; + off_t offset; char *p, *data; static int max_reply_size = -1; @@ -410,7 +418,8 @@ handle_pread (char *own_buf, int *new_packet_len) static void handle_pwrite (char *own_buf, int packet_len) { - int fd, ret, len, offset; + int fd, ret, len; + off_t offset; char *p, *data; p = own_buf + strlen ("vFile:pwrite:");