c - Getrusage inline assembly -


i trying implement getrusage function client server program using sockets , of running on freebsd. want print out processor time usage , memory usage.

i have tried implement following code getting output illegal instrucion (core dumped)

int getrusage(int who, struct rusage *usage){      int errorcode;     __asm__(     "syscall"     : "=a" (errorcode)     : "a" (117), "d"  (who), "s" (usage)  //const sysgetrusage : scno = 117     : "memory"     );      if (errorcode<0) {         printf("error");     }     return 1;   } 

update: have tried run 0 values or random number value or negative number values. ideas missing?

int getrusage(int who, struct rusage *usage){      int errorcode;     __asm__("push $0;"                 "push %2;"                 "push %1;"                 "movl $117, %%eax;"                 "int $0x80;"                 :"=r"(errorcode)                 :"d"(who),"s"(usage)                 :"%eax"         );      if (errorcode<0) {         printf("error");     }     return 1;  } 

i use system call write more likely, giving me compilation warning: passing arg 1 of 'strlen' makes pointer integer without cast

edit: (this working code now, regarding comment)

struct rusage usage; getrusage(rusage_self,&usage); char tmp[300];  write(i, "memory: ", 7); sprintf (tmp, "%ld", usage.ru_maxrss); write(i, tmp, strlen(tmp)); write(i, "time: ", 5); sprintf (tmp, "%lds", usage.ru_utime.tv_sec); write(i, tmp, strlen(tmp)); sprintf (tmp, "%ldms", usage.ru_utime.tv_usec); write(i, tmp, strlen(tmp)); 

any ideas wrong?

the reason getting illegal instruction error because syscall instruction available on 64-bit freebsd running 64-bit program. serious issue since 1 of comments suggests code running on 32-bit freebsd.

under normal circumstances don't need write own getrusage since part of c library (libc) on platform. appears have been tasked inline assembly.


64-bit freebsd , syscall instruction

there bit of bug in 64-bit code since syscall destroys contents of rcx , r11. code may work may fail in future program expands , enable optimizations. following change adds 2 registers clobber list:

int errorcode;     __asm__(         "syscall"         : "=a" (errorcode)         : "a" (117), "d"  (who), "s" (usage)  //const sysgetrusage : scno = 117         : "memory", "rcx", "r11" ); 

using memory clobber can lead generation of inefficient code use if necessary. become more of expert need memory clobber can eliminated. have used function following if wasn't allowed use c library version of getrusage:

int getrusage(int who, struct rusage *usage){      int errorcode;     __asm__(         "syscall"         : "=a"(errorcode), "=m"(*usage)         : "0"(117), "d"(who), "s"(usage)         : "rcx", "r11"     );      if (errorcode<0) {         printf("error");     }     return errorcode; } 

this uses memory operand output constraint , drops memory clobber. since compiler knows how large rusage structure , =m says output constraint modifies memory don't need need memory clobber.


32-bit freebsd system calls via int 0x80

as mention in comments , updated code, make system call in 32-bit code in freebsd have use int 0x80. described in freebsd system calls convention. parameters pushed on stack right left , must allocate 4 bytes on stack pushing 4 byte value onto stack after push last parameter.

your edited code has few bugs. first push 4 bytes before rest of arguments. need push after. need adjust stack after int 0x80 reclaim stack space used arguments passed. pushed 3 4-byte values on stack, need add 12 esp after int 0x80.

you need memory clobber because compiler doesn't know have modified memory @ all. because way have done constraints data in variable usage gets modified compiler doesn't know what.

the return value of int 0x80 in eax use constraint =r. should have been =a since return value returned in eax. since using =a tells compiler eax clobbered don't need list clobber anymore.

the modified code have looked like:

int getrusage(int who, struct rusage *usage){      int errorcode;     __asm__("push %2;"             "push %1;"             "push $0;"             "movl $117, %%eax;"             "int $0x80;"             "add $12, %%esp"             :"=a"(errorcode)             :"d"(who),"s"(usage)             :"memory"             );      if (errorcode<0) {         printf("error");     }     return errorcode; } 

another way 1 have written more advanced techniques is:

int getrusage(int who, struct rusage *usage){      int errorcode;     __asm__("push %[usage]\n\t"             "push %[who]\n\t"             "push %%eax\n\t"             "int $0x80\n\t"             "add $12, %%esp"             :"=a"(errorcode), "=m"(*usage)             :"0"(117), [who]"ri"(who), [usage]"r"(usage)             :"cc" /* don't need x86 inline asm use clarity */         );      if (errorcode<0) {         printf("error");     }     return errorcode; } 

this uses label (usage , who) identify each parameter rather using numerical positions %3, %4 etc. makes inline assembly easier follow. since 4-byte value can pushed onto stack before int 0x80 can save few bytes pushing contents of register. in case used %%eax. uses =m constraint did in 64-bit example.

more information on extended inline assembler can found in gcc documentation.


Comments

Popular posts from this blog

php - Permission denied. Laravel linux server -

google bigquery - Delta between query execution time and Java query call to finish -

python - Pandas two dataframes multiplication? -