0

I have a buggy function in a shared library. It enters infinite loop when recv() returns 0.

There's no source code. I was able to decompile the buggy part and change some processor instructions without resizing the function, but there's no room for a full fix.

I want to compile the new version with gcc and put it back into the library. The function uses some global and, what's worse, static variables. The fixed function is bigger than the original one, so it can't be put into the same place.

Here it is:

#include <sys/types.h>
#include <stdio.h>

#define PM_ERROR_INVALID_CLIENT            210

typedef struct
{
  int   code;
  int   detail_code;
  char* message;
} pm_error;

typedef struct 
{
  char *server_name;
  int port;
  int socket_descriptor;
  int status;
  int timeout;
} pm_client;

 extern int debug;
 int pmprotocol_read(pm_client *param0_client, char *param1_data, int param2_length, pm_error *param3_error)
 {
   size_t local_bytes_received;
   size_t local_total_bytes;
   int local_status;
   char local_message[128];
   int local_retval;
   // init globals pointer
   // copy params to stack
   // pmprotocol.c:896
   if (debug > 0)
   {
     fprintf(
       stderr
       ,"pmprotocol_read:enter\n"  
       );
   }
   // pmprotocol.c:897
   // pmprotocol.c:898
   local_retval = 0;
   // pmprotocol.c:900
   local_status = 0;
   // pmprotocol.c:901
   // pmprotocol.c:902
   if (param0_client->status != 0)
   {
   // pmprotocol.c:904
     pm_error_set_internal(
       param3_error
       ,"pmprotocol_read"
       ,"function called with invalid client"
       ,PM_ERROR_INVALID_CLIENT
     );
   // pmprotocol.c:905
     return 1;
   }
   // pmprotocol.c:908
   local_retval = pmprotocol_waitfor_read(param0_client, param3_error);
   // pmprotocol.c:909
   if (local_retval != 0)
   {
     return local_retval;
   }
   // pmprotocol.c:910
   // pmprotocol.c:911
   local_total_bytes = 0;
   //pmprotocol.c:913
   while ((size_t)param2_length > local_total_bytes)
   {
     //pmprotocol.c:915
     local_bytes_received = recv(
        param0_client->socket_descriptor
        ,param1_data + local_total_bytes
        ,param2_length - local_total_bytes
        ,0
        );
     //pmprotocol.c:924
     local_total_bytes += local_bytes_received;
   }
   //pmprotocol.c:928
   if (debug > 1)
     pmutil_dump_buf(param1_data, param2_length, stderr, "From wire");
   //pmprotocol.c:929
   if (debug > 0)
     fprintf(
       stderr
       ,"pmprotocol_read:finish\n"
       );
   //pmprotocol.c:930
   return local_status;
 }

The disassembly:

.skip 0x697c
! typedef long long longlong_t;
! #include "../include/pmtypes.h"
! #include "../include/pmclient.h"
! extern int debug;
global_debug = 0x17c
global__iob = 0x2ac
global_LLC54 = 0x168 ! // "pmprotocol_read:enter\n"
global_LLC56 = 0x170 ! // "From wire"
global_LLC57 = 0x174 ! // "pmprotocol_read:finish\n"
global_LLC55 = 0x16c ! // "pmprotocol_read"
global_LLC38 = 0x128 ! // "function called with invalid client"

.type pmprotocol_read , STT_FUNC
.global pmprotocol_read
.align  4

! int pmprotocol_read(pm_client *param0_client, char *param1_data, int param2_length, pm_error *param3_error)
pmprotocol_read:

pmutil_dump_buf_plt = pmprotocol_read+81856
recv_plt = pmprotocol_read+83308
fprintf_plt = pmprotocol_read+81724
pm_error_set_internal_plt = pmprotocol_read+81868
pmprotocol_waitfor_read_plt = pmprotocol_read+82360

globals = 0x13f70

param0_client = 0x44
param1_data = 0x48
param2_length = 0x4c
param3_error = 0x50

! {

     auto_retval = -168

!   size_t local_bytes_received;
     local_bytes_received = -164

!   size_t local_total_bytes;
     local_total_bytes = -160

!   int local_status;
     local_status = -156

!   char local_message[128];
     local_message = -152

!   int local_retval;
     local_retval = -20

!   // init globals pointer
     0xff38691c <+0>:     save  %sp, -264, %sp
     0xff386920 <+4>:     sethi  %hi(globals), %l7
     0xff386924 <+8>:     call  .-9152
     0xff386928 <+12>:    add  %l7, %lo(globals), %l7
                                                  ! now %l7==0x13be8
                                                  ! "No function contains program counter for selected frame."
                                                  ! now %l7==0xff39a50c

!   // copy params to stack
     0xff38692c <+16>:    st  %i0, [ %fp + param0_client ]
     0xff386930 <+20>:    st  %i1, [ %fp + param1_data ]
     0xff386934 <+24>:    st  %i2, [ %fp + param2_length ]
     0xff386938 <+28>:    st  %i3, [ %fp + param3_error ]

!   // pmprotocol.c:896
!   if (debug > 0)
     0xff38693c <+32>:    sethi  %hi(0), %g1
     0xff386940 <+36>:    or  %g1, global_debug, %g1     ! global_debug
     0xff386944 <+40>:    ld  [ %l7 + %g1 ], %g1             ! (%l7 + %g1)==0xff39a688
                                                             ! now %g1==0xff39ad54
     0xff386948 <+44>:    ld  [ %g1 ], %g1
     0xff38694c <+48>:    cmp  %g1, 0
     0xff386950 <+52>:    ble  .+48 ! <pmprotocol_read+100>
     0xff386954 <+56>:    nop
!   {
!     fprintf(
!       stderr
         0xff386958 <+60>:    sethi  %hi(0), %g1
         0xff38695c <+64>:    or  %g1, global__iob, %g1     ! global__iob
         0xff386960 <+68>:    ld  [ %l7 + %g1 ], %g1
         0xff386964 <+72>:    add  %g1, 0x20, %o0

!       ,"pmprotocol_read:enter\n"  
         0xff386968 <+76>:    sethi  %hi(0), %g1
         0xff38696c <+80>:    or  %g1, global_LLC54, %g1     ! global_LLC54  
         0xff386970 <+84>:    ld  [ %l7 + %g1 ], %g1
         0xff386974 <+88>:    mov  %g1, %o1

!       );
         0xff386978 <+92>:    call  fprintf_plt
         0xff38697c <+96>:    nop
!   }

!   // pmprotocol.c:897
!   // pmprotocol.c:898
!   local_retval = 0;
     0xff386980 <+100>:   clr  [ %fp + local_retval ]
!   // pmprotocol.c:900
!   local_status = 0;
     0xff386984 <+104>:   clr  [ %fp + local_status ]

!   // pmprotocol.c:901
!   // pmprotocol.c:902
!   if (param0_client->status != 0)
     0xff386988 <+108>:   ld  [ %fp + param0_client ], %g1
     0xff38698c <+112>:   ld  [ %g1 + 0xc ], %g1
     0xff386990 <+116>:   cmp  %g1, 0
     0xff386994 <+120>:   be  .+72 ! <pmprotocol_read+192>
     0xff386998 <+124>:   nop
!   {
!   // pmprotocol.c:904
!     pm_error_set_internal(
!       param3_error
         0xff38699c <+128>:   ld  [ %fp + param3_error ], %o0

!       ,"pmprotocol_read"
         0xff3869a0 <+132>:   sethi  %hi(0), %g1
         0xff3869a4 <+136>:   or  %g1, global_LLC55, %g1     ! global_LLC55
         0xff3869a8 <+140>:   ld  [ %l7 + %g1 ], %g1
         0xff3869ac <+144>:   mov  %g1, %o1

!       ,"function called with invalid client"
         0xff3869b0 <+148>:   sethi  %hi(0), %g1
         0xff3869b4 <+152>:   or  %g1, global_LLC38, %g1     ! global_LLC38
         0xff3869b8 <+156>:   ld  [ %l7 + %g1 ], %g1
         0xff3869bc <+160>:   mov  %g1, %o2

!       ,PM_ERROR_INVALID_CLIENT
         0xff3869c0 <+164>:   mov  0xd2, %o3
!     );
       0xff3869c4 <+168>:   call  pm_error_set_internal_plt
       0xff3869c8 <+172>:   nop

!   // pmprotocol.c:905
!     return 1;
       0xff3869cc <+176>:   mov  1, %g1     ! 0x1
       0xff3869d0 <+180>:   st  %g1, [ %fp + auto_retval ]
       0xff3869d4 <+184>:   b  .+320 ! <pmprotocol_read+504>
       0xff3869d8 <+188>:   nop
!   }

!   // pmprotocol.c:908
!   local_retval = pmprotocol_waitfor_read(param0_client, param3_error);
     0xff3869dc <+192>:   ld  [ %fp + param0_client ], %o0
     0xff3869e0 <+196>:   ld  [ %fp + param3_error ], %o1
     0xff3869e4 <+200>:   call  pmprotocol_waitfor_read_plt
     0xff3869e8 <+204>:   nop
     0xff3869ec <+208>:   mov  %o0, %g1
     0xff3869f0 <+212>:   st  %g1, [ %fp + local_retval ]

!   // pmprotocol.c:909
!   if (local_retval != 0)
     0xff3869f4 <+216>:   ld  [ %fp + local_retval ], %g1
     0xff3869f8 <+220>:   cmp  %g1, 0
     0xff3869fc <+224>:   be  .+24 ! <pmprotocol_read+248>
     0xff386a00 <+228>:   nop
!   {
!     return local_retval;
       0xff386a04 <+232>:   ld  [ %fp + local_retval ], %g1
       0xff386a08 <+236>:   st  %g1, [ %fp + auto_retval ]
       0xff386a0c <+240>:   b  .+264 ! <pmprotocol_read+504>
       0xff386a10 <+244>:   nop
!   }

!   // pmprotocol.c:910
!   // pmprotocol.c:911
!   local_total_bytes = 0;
     0xff386a14 <+248>:   clr  [ %fp + local_total_bytes ]

!   //pmprotocol.c:913
!   while ((size_t)param2_length > local_total_bytes)
     0xff386a18 <+252>:   ld  [ %fp + param2_length ], %o5
     0xff386a1c <+256>:   ld  [ %fp + local_total_bytes ], %g1
     0xff386a20 <+260>:   cmp  %o5, %g1
     0xff386a24 <+264>:   bleu  .+88 ! <pmprotocol_read+352>
     0xff386a28 <+268>:   nop
!   {

!     //pmprotocol.c:915
!     local_bytes_received = recv(
         0xff386a2c <+272>:   ld  [ %fp + param0_client ], %o3
         0xff386a30 <+276>:   ld  [ %fp + param1_data ], %o5         
         0xff386a34 <+280>:   ld  [ %fp + local_total_bytes ], %g1 
         0xff386a38 <+284>:   add  %o5, %g1, %o4                
         0xff386a3c <+288>:   ld  [ %fp + param2_length ], %o5
         0xff386a40 <+292>:   ld  [ %fp + local_total_bytes ], %g1
         0xff386a44 <+296>:   sub  %o5, %g1, %g1

!        param0_client->socket_descriptor
          0xff386a48 <+300>:   ld  [ %o3 + 8 ], %o0

!        ,param1_data + local_total_bytes
          0xff386a4c <+304>:   mov  %o4, %o1                      

!        ,param2_length - local_total_bytes
          0xff386a50 <+308>:   mov  %g1, %o2

!        ,0
          0xff386a54 <+312>:   clr  %o3
!        );
          0xff386a58 <+316>:   call  recv_plt
          0xff386a5c <+320>:   nop
          0xff386a60 <+324>:   st  %o0, [ %fp + local_bytes_received ]

!     //pmprotocol.c:924
!     local_total_bytes += local_bytes_received;
       0xff386a64 <+328>:   ld  [ %fp + local_total_bytes ], %o5
       0xff386a68 <+332>:   ld  [ %fp + local_bytes_received ], %g1
       0xff386a6c <+336>:   add  %o5, %g1, %g1
       0xff386a70 <+340>:   st  %g1, [ %fp + local_total_bytes ]

!   }
     0xff386a74 <+344>:   b  .-92 ! <pmprotocol_read+252>
     0xff386a78 <+348>:   nop

!   //pmprotocol.c:928
!   if (debug > 1)
     0xff386a7c <+352>:   sethi  %hi(0), %g1
     0xff386a80 <+356>:   or  %g1, global_debug, %g1     ! global_debug
     0xff386a84 <+360>:   ld  [ %l7 + %g1 ], %g1
     0xff386a88 <+364>:   ld  [ %g1 ], %g1
     0xff386a8c <+368>:   cmp  %g1, 1
     0xff386a90 <+372>:   ble  .+56 ! <pmprotocol_read+428>
     0xff386a94 <+376>:   nop
!     pmutil_dump_buf(param1_data, param2_length, stderr, "From wire");
       0xff386a98 <+380>:   ld  [ %fp + param1_data ], %o0
       0xff386a9c <+384>:   ld  [ %fp + param2_length ], %o1
       0xff386aa0 <+388>:   sethi  %hi(0), %g1
       0xff386aa4 <+392>:   or  %g1, global__iob, %g1     ! global__iob
       0xff386aa8 <+396>:   ld  [ %l7 + %g1 ], %g1
       0xff386aac <+400>:   add  %g1, 0x20, %o2
       0xff386ab0 <+404>:   sethi  %hi(0), %g1
       0xff386ab4 <+408>:   or  %g1, global_LLC56, %g1     ! global_LLC56
       0xff386ab8 <+412>:   ld  [ %l7 + %g1 ], %g1
       0xff386abc <+416>:   mov  %g1, %o3
       0xff386ac0 <+420>:   call  pmutil_dump_buf_plt
       0xff386ac4 <+424>:   nop

!   //pmprotocol.c:929
!   if (debug > 0)
     0xff386ac8 <+428>:   sethi  %hi(0), %g1
     0xff386acc <+432>:   or  %g1, global_debug, %g1     ! global_debug
     0xff386ad0 <+436>:   ld  [ %l7 + %g1 ], %g1
     0xff386ad4 <+440>:   ld  [ %g1 ], %g1
     0xff386ad8 <+444>:   cmp  %g1, 0
     0xff386adc <+448>:   ble  .+48 ! <pmprotocol_read+496>
     0xff386ae0 <+452>:   nop
!     fprintf(
!       stderr
         0xff386ae4 <+456>:   sethi  %hi(0), %g1
         0xff386ae8 <+460>:   or  %g1, global__iob, %g1     ! global__iob
         0xff386aec <+464>:   ld  [ %l7 + %g1 ], %g1
         0xff386af0 <+468>:   add  %g1, 0x20, %o0
!       ,"pmprotocol_read:finish\n"
         0xff386af4 <+472>:   sethi  %hi(0), %g1
         0xff386af8 <+476>:   or  %g1, global_LLC57, %g1     ! global_LLC57
         0xff386afc <+480>:   ld  [ %l7 + %g1 ], %g1
         0xff386b00 <+484>:   mov  %g1, %o1
!       );
         0xff386b04 <+488>:   call  fprintf_plt
         0xff386b08 <+492>:   nop
!   //pmprotocol.c:930
!   return local_status;
     0xff386b0c <+496>:   ld  [ %fp + local_status ], %g1
     0xff386b10 <+500>:   st  %g1, [ %fp + auto_retval ]

     0xff386b14 <+504>:   ld  [ %fp + auto_retval ], %i0
     0xff386b18 <+508>:   ret
     0xff386b1c <+512>:   restore
! }
basin
  • 3,949
  • 2
  • 27
  • 63
  • Was able to add section with objcopy. But ld complains about section not mapped to load segment. – basin Jul 10 '13 at 18:56

1 Answers1

0

Use the LD_PRELOAD trick:

What is the LD_PRELOAD trick?

Community
  • 1
  • 1
Rayson Ho
  • 26
  • 2