How do I reimplement realloc in assembly on mac os x? - c

I don't need any of this, it's for fun
I implemented realloc on linux before using map and mremap. I ran dtruss on the below code and I see two write calls, nothing in between. Using bash and time b.c is significantly slower than a.c which leaves me to believe realloc doesn't use a memcpy (and likely changes virtual pages).
If I wanted to implement my own C library or write a realloc in assembly how would I implement it to get as good performance as a.c?
% cat a.c b.c
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
write(1, "Hel", 3);
void*p1=malloc(1024*1024*512);
memset(p1, '1', 1024*1024*512);
malloc(4096);
void*p =realloc(p1, 1024*1024*1024);
memset(p+1024*1024*512, '0', 1024*1024*512);
write(1, "lo\n", 3);
}
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
write(1, "Hel", 3);
void*p1=malloc(1024*1024*512);
memset(p1, '1', 1024*1024*512);
void*p =malloc(1024*1024*1024);
memcpy(p, p1, 1024*1024*512);
memset(p+1024*1024*512, '0', 1024*1024*512);
write(1, "lo\n", 3);
}

Related

Again a question about reading a directory file with C

How we can use C functions open/read/close properly in order to read a linux directory?. I notice serveral others asked this question before, about on reading directories in C, also that several ones suggest the use of readdir/opendir/closedir functions, I know, but RnK book (the C programming language) in fact define or introduces those readdir/opendir/closedir/ functions, the problem is that read() function "not read" properly directories; it returns -1 instead of the number of bytes readed. Is there any change into the actual read() C function that produces this or it is necesary modifications to read()?
Here is my example code:
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
int fd;
size_t nbytes;
ssize_t bytes_read;
char buf[20];
fd=open(".",O_RDONLY,0);
nbytes = sizeof(buf);
bytes_read = read(fd, buf, nbytes);
printf("Buf size: %ld file descriptor: %d bytes readed:
%ld\n",nbytes,fd,bytes_read);
}
Compiling above code in ubuntu linux read gives bytes_read = -1.
Thanks in advance

SIGSEGV, after mmapping area

I am trying to revive process from core dump after SIGQUIT.
I really want that piece of virtual memory, yet I get SIGSEGV when I try to map it.
EDIT: This area isn't free: 0xf75d2000 - 0xf7774000, but still i want to have it.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ucontext.h>
#include <elf.h>
#include <sys/procfs.h>
#include <sys/user.h>
#include <linux/unistd.h>
#include <linux/unistd.h>
#include <asm/ldt.h>
#include <signal.h>
bool flag = false;
int argc2;
char ** argv2;
int main2(){
FILE * file = fopen("/proc/self/maps", "r");
if (file) {
char c;
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
fflush(stdout);
void* res = mmap((void*)(0xf75d2000), 0x001a5000, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
return 0;
}
int main(int argc, char ** argv){
argc2 = argc;
argv2 = argv;
ucontext_t cont;
getcontext (&cont);
if(!flag){
void* a = mmap((void*)0x34B000, 81920, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if(a == MAP_FAILED){
printf("mmapfail");
return 1;
}
cont.uc_mcontext.gregs[REG_ESP] = 0x355000;
flag = true;
setcontext(&cont);
} else{
exit(main2());
}
}
I'm compiling it with:
gcc -static -Wl,-Ttext=0x4A9480,--build-idone,-Tdata=0x639480,--section-start=.plt=0x3B9480,--section-start=.rel.plt=0x3AF480,--section-start=.note.ABI-tag=0x39B480 main.c -o main -m32
The address you are trying to map (0xf75d2000) is above the userspace/kernel split in virtual memory. If your kernel is configured with CONFIG_VMSPLIT_3G, you can't map arbitrary addresses above 0xc0000000.
The existing mappings were setup in kernel to expose the vDSO space (to assist with system calls).
Of course you get a SEGV. You map things with MAP_FIXED into some address that doesn't belong to you, then you pull the stack from under your feet. You cannot do this.
The address space is not yours to mess around in. MAP_FIXED is only safe for overwriting earlier mappings. You can possibly play around in it in a single experiment where you'll throw away the program afterwards, but any other use is just not going to work.
Right now your call to setcontext will crash because it doesn't know where to return. Do you even know how function calls and the stack interact? Your call to setcontext saves the return address on the stack, then setcontext changes the stack pointer then it tries to return and dies because it reads 0 as the return address (or setcontext maybe saves the old stack pointer in some other register and will restore it from that register before it returns and what crashes is your other mmap that overwrites the real stack). Please don't do this. Your only chance to reliably change stacks without being the operating system is to set up a signal handler with sigaltstack, catch that signal and never return from the signal handler.
But since you're mapping the memory for your new stack with MAP_FIXED into some random address you'll probably overwrite some other important data structure and it still won't work.
The address space needs to be claimed before other areas are claimed, therefore it needs to be claimed in the executable's metadata.
Create an section in assembly language, then specify it's address in a command line argument to the linker.
For example:
#include <stdio.h>
extern char mem[];
asm (R"(
.section fixed, "aw", #nobits
.global mem
mem:
.zero 0x20000000
)");
int main() {
printf("mem = %p\n", mem);
}
Compile and link with:
gcc -O2 -Wl,--section-start=fixed=0x40000000 -fno-pie -no-pie test.c
Unfortunately using GCC's __attribute__((Section("fixed"))) on a variable definition GCC results in a executable bloated with zeros.

How to fix Segmentation fault in C

Hello i wrote my c program which will be run on linux.
I am trying to make my own shell for linux.
I have the following code below...
#include <limits.h>
#include <libgen.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
int main(void){
int i = 0;
int k = 0;
int argsCount = 0;
char inputBuffer[MAX_LINE]; /*buffer to hold command entered */
int background; /* equals 1 if a command is followed by '&' */
char *args[MAX_LINE/2 + 1]; /*command line arguments */
pid_t tpid ;
pid_t child_pid;
int child_status;
char path[PATH_MAX+1];
char *progpath = strdup(args[0]);
char *prog = basename(progpath);
char temp[MAX_LINE];
}
It'is compiling well but when i try to run the code it gives me segmentation fault error
How can i fix it and why i take this error?
Your main has a wrong signature. You want
int main(int argsCount, char**args) {
and of course you should remove the internal declaration of argCount & args inside your main.
Perhaps you want instead your args & argCount to contain the parsed arguments of your own shell (but you still have to give a good signature to your main, conventionally and very often int main(int argc, char**argv).... you probably want your shell to accept the -c argument as most shells do, this would ease debugging with simplistic test cases). Then you should initialize them, and you should read some line (probably with getline) in a loop.
As I commented, you should compile with all warnings & debug info:
gcc -Wall -Wextra -g yoursource.c -o yourprog
Then use gdb ./yourprog to debug your program (see GDB documentation). valgrind should also be helpful. Of course, be sure to develop on a Linux system!
BTW, your program is not a convincing start for a shell. Use strace on some existing shell to understand what a shell needs to do. Study the source code of some existing free software shell (e.g. sash, fish, GNU bash ...). Read Advanced Linux Programming

pthread_cancel don't work under solaris

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
char a[]="Hello";
void * thread_body(void * param) {
while(1)
printf("%s\n", param);
}
int main(int argc, char *argv[]) {
pthread_t threadHello;
int code;
pthread_create(&threadHello, NULL, thread_body, a);
pthread_cancel(threadHello);
pthread_exit(0);
}
When I compile and run this under Solaris 10 (SunOS 5.10), it doesn't stop. But under Linux it works as intended.
Per POSIX, printf (and all of stdio) may be a cancellation point. It is not required to be. I suspect Solaris just doesn't choose to make it one. Have you tried another function like sleep here?
If you really need printf to be cancellable, you'll probably need to implement your own printf-like function as a wrapper for dprintf, but that won't work so well if you're depending on the builtin locking functionality of stdio..

What does -fPIC Mean when compiling a shared library

I am trying to create a shared library in linux I get the following error when trying to compile this :
relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
If i remove the contents of GetCrc16 it Works. What am I doing wrong ?
/*
* main.c
*
* Created on: Jul 3, 2012
* Author: opc0de
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <mysql/mysql.h>
#include <arpa/inet.h>
#include <curl/curl.h>
typedef struct param
{
int * csock;
char * IMEI;
}param;
#define DAEMON_NAME "MEGA_TRACKER"
static const unsigned short crctab16[] =
{
0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,
0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,
0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,
0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,
0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,
0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,
0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,
0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,
0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,
0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,
0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,
0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,
0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,
0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,
0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,
0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,
0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,
0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,
0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,
0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,
0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,
0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,
0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,
0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,
0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,
0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,
0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,
0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,
0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,
0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,
};
unsigned char response[] = { 0x78, 0x78, 0x05 , 0x00 ,0x00, 0x00, 0x00, 0x00,0x0D, 0x0A};
char Hexars[] = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b','c', 'd', 'e', 'f' };
unsigned short GetCrc16(const unsigned char* pData, int nLength)
{
unsigned short fcs = 0xffff; // initialize
while(nLength>0){
fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
nLength--;
pData++;
}
return ~fcs;
}
-fPIC instructs the compiler to compile your code as Position Independent Code. This is needed so that the machine code executed properly regardless of the absolute address.
These are needed mainly for shared libraries, as the same library code can be loaded in a location in each program's address space where it will not overlap with other uses of memory etc.
Following links can provide more info.
Wikipedia: http://en.wikipedia.org/wiki/Position_independent_code
SO: Why isn't all code compiled position independent?
The command line option -fPIC means make position independent code. This is needed when compiling shared objects (.so) for 64bit. You were able to get away without using it on 32bit; even though it was recommended.

Resources