Re: [PATCH] Fix call functions command bug in 64-bit programs for AIX

Aditya Kamath1 via Gdb-patches
2022-11-11T17:53:40Z

Hi Ulrich,

> This is not how the GDB register cache is working. Can you explain in
> more detail what exactly you're refering to here?

Let us say we have a simple function, like print_Num (int a, long b) which prints these numbers a and b and the program is in 64-bit mode. If the programs are debugged normally, things work fine. But if a user attempts to see what the function does with the command call print_Num (int a, long b) then in the register assigned for function parameters the value 0 is getting dumped. What is happening is the pointer that is pointing to the input numbers a and b in the regcache->raw_supply which was addr previously is not aliging our values. It dumps the higher 32 bits in lower 32 bits and lower 32 bits to the higher which I figured out when I extracted it byte by byte using long pointer [long addr64 variable in the patch]. If int pointer is used in 64-bit mode in raw_supply code's second parameter, then memcpy () before rs6000_ptrace64 () fails to copy the right 8 bytes in buffer as int addr[64] is pointing to the wrong information. Overall, we were not pointing to the right place with the pointers passed to these functions.

>- what does ARCH64() return?
True in 64 bit mode and false in 32 bit mode

> - what does register_size(...) return for those registers?
8 in 64 bit mode, 4 in 32 bit mode
(for GPRs with a 64-bit inferior it should return 8, if
it doesn't that's probably the root cause of the problem)
> - what value does ptrace return in your case?
It returns the data parameter value that is passed as the calls are successful.

Consider this code below:-

#include "stdio.h"

int num2print(long num, float num2, int num3, double num4) {

if (num == 0) {

printf("R0\n");

return 0;

}

if (num == 1) {

printf("R1\n");

return 1;

}

printf("R%d\n",num);

printf("R%f\n",num2);

printf("R%d\n",num3);

printf("R%lf\n",num4);

return num;

}

int main(int argc, char** argv)

{

printf("Hi Bangalore %x\n",num2print(27, 16, 13, 9.9));

return 0;

}

The output before patch in 64 bit mode is:-

Reading symbols from /home/XYZ...

(gdb) b main

Breakpoint 1 at 0x100007dc: file /home/XYZ.c, line 22.

(gdb) r

Starting program: /home/XYZ

BFD: /usr/lib/libc.a(/usr/lib/libc.a(shr_64.o)): wrong auxtype 0xff for storage class 0x2

BFD: /usr/lib/libc.a(/usr/lib/libc.a(shr_64.o)): wrong auxtype 0xff for storage class 0x6b

Breakpoint 1, main (argc=1, argv=0xffffffffffffad0) at /home/XYZ.c:22

22 printf("Hi Bangalore %x\n",num2print(27, 16, 13, 9.9));

(gdb) call num2print

$1 = {int (long, float, int, double)} 0x1000006a0 <num2print>

(gdb) call num2print (2, 3, 4, 5)

R2

R3.000000

R0

R5.000000

$2 = 2

(gdb)

The output highlighted in bold should have been R4 but is R0.. The datatype of the variable is long and if you print the output byte by byte before memcpy and if you have taken a long pointer to raw_supply, one realises 4 which is lower 32 bits is in higher bits and 0 in higher bits is in lower bits which was the pointer will be holding. The pointer getting the value in raw_supply was pointing to elsewhere instead of 4 [ the lower bits] if it is an int pointer.

Kindly let me know if you need more details. I am only trying to re align to correct the things my pointer in raw_supply function has messed up. Let me know if there can be a better way you have in mind.

Have a nice day.

Thanks and regards,
Aditya.

________________________________
From: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Sent: 08 November 2022 19:00
To: gdb-patches@sourceware.org <gdb-patches@sourceware.org>; Aditya Kamath1 <Aditya.Kamath1@ibm.com>; simon.marchi@efficios.com <simon.marchi@efficios.com>
Cc: Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
Subject: Re: [PATCH] Fix call functions command bug in 64-bit programs for AIX

Aditya Kamath1 <Aditya.Kamath1@ibm.com> wrote:

>The issue is that when a user attempts to test the return type or print
>statements via the call "FUNC_NAME (parameter A, parameter B)" command,
any input be it parameter A or B is taken in little endian format from
>the GDB cache. But AIX is using Big endian format.

>For example, if we have a value 21 as type long then the higher 32 bits
>[ which is 0 in number 21] were stored in lower 32 bits and lower 32 bits
>[ represent 21 in the number 21] is stored in higher 32 bits.

This is not how the GDB register cache is working. Can you explain in
more detail what exactly you're refering to here?

The register cache holds a sequence of bytes for each register. The
number of bytes in the cache depends on the size of that register as
defined by the architecture. The contents of those bytes are *always*
assumed to be in big-endian byte order on AIX.

For 64-bit inferior processes, GDB assumes that the ptrace call
always uses a 64-bit buffer, even if the register size is only 4.
To handle these cases, the current code will convert between the
two formats, which looks correct to me: in the fetch_register
case, it will retrieve an 8-byte value from ptrace, convert that
value (correctly, also for big-endian) to an 4-byte value, and
pass that 4-byte value to raw_supply, which should expect 4 bytes
in this case because the register_size is 4.

To understand what's going on exactly I need more details:
- what does ARCH64() return?
- what does register_size(...) return for those registers?
(for GPRs with a 64-bit inferior it should return 8, if
it doesn't that's probably the root cause of the problem)
- what value does ptrace return in your case?

In any case, explicitly listing specific register numbers by ABI
is definitely wrong here. This routine must correctly handle
any register, it does not matter what the ABI usage is.

Bye,
Ulrich