Segmentation fault after declaring a variable inside structure - struct

I am currently working on a project using network simulator 2. When I add variable inside the structure re_block, the program compiles but gives me segmentation fault during runtime. When i declare the variable as static there is no runtime error. Someone please explain this.
struct re_block {
# if __BYTE_ORDER == __BIG_ENDIAN
u_int16_t g : 1;
u_int16_t prefix : 7;
u_int16_t res : 2;
u_int16_t re_hopcnt : 6;
# elif __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res : 2;
u_int16_t re_hopcnt : 6;
u_int16_t g : 1;
u_int16_t prefix : 7;
# else
# error "Adjust your <bits/endian.h> defines"
# endif
u_int32_t re_node_addr;
u_int32_t re_node_seqnum;
};
#define MAX_RE_BLOCKS
typedef struct {
u_int32_t m : 1;
u_int32_t h : 2;
u_int32_t type : 5;
u_int32_t len : 12;
u_int32_t ttl : 6;
u_int32_t i : 1;
u_int32_t a : 1;
u_int32_t s : 1;
u_int32_t res1 : 3;
u_int32_t target_addr;
u_int32_t target_seqnum;
u_int8_t thopcnt : 6;
u_int8_t res2 : 2;
struct re_block re_blocks[MAX_RE_BLOCKS];
} RE;
I want to add two float variables in struct re_block. Please help

Using a memory debugging tool such as valgrind, can you find the place in the code where the segfault occurs? My guess would be that there is some runtime code that takes advantage of the data layout of the re_block struct, for example by casting a pointer to a re_block instance to type (u_int16_t *) and dereferencing as a means of getting the first member, rather than using the operator ->. Adding members to the struct can change the layout of the data, so code that uses such tricks may break.

Related

Incorrect SHA digest for very long messages when using kernel crypto

I'm trying to compute the hash digest using SHA-1 using kernel crypto. I get the right results for messages under 4096 bytes. Anything beyond that is incorrect. The test itself does not fail but gives incorrect responses.
Left side shows output from OpenSSL and right side for kernel crypto. The reason I know left side (OpenSSL) gives right results is because the results were validated by a lab. In the image, the message length is 32984 which is 4123 bytes.
My code is shown below:
int numpages = (msgLength / PAGE_SIZE);
if ( msgLength % PAGE_SIZE )
numpages++; // Overflow
struct crypto_shash *tfm = NULL;
struct shash_desc *desc = NULL;
unsigned char *page_msg[numpages];
unsigned char *page_hash;
int i, msg_remaining;
tfm = crypto_alloc_shash("sha1", 0, 0);
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
if (!desc) {
LOG_ERROR("Unable to allocate struct shash_desc\n");
goto free_return;
}
desc->tfm = tfm;
desc->flags = 0;
// temporary storage for hash in block-memory
page_hash = (unsigned char*)get_zeroed_page(GFP_KERNEL);
// setup message in block-memory
i=0;
msg_remaining = msgLength;
while ( msg_remaining > 0 ) {
page_msg[i] = (unsigned char*)get_zeroed_page(GFP_KERNEL);
memcpy(page_msg[i], msg + (i * PAGE_SIZE), (msg_remaining > PAGE_SIZE) ? PAGE_SIZE : msg_remaining);
i++;
msg_remaining -= PAGE_SIZE;
}
// do the operation
crypto_shash_init(desc);
if ( 0 != crypto_shash_digest(desc, page_msg[0], msgLength, page_hash) ) {
LOG_ERROR("Bad Digest Returned\n");
goto free_return;
}
free_return:
crypto_free_shash(tfm);
free_page((unsigned long)page_hash);
for ( i = 0; i < numpages; i++ ) {
free_page((unsigned long)page_msg[i]);
}

Error initialization from incompatible pointer of IOCTL function in Linux kernel 4.8.0-53-generic Linux Mint 64 bit

I've got an error while writing a char device module, using Ioctl command.
static struct file_operations my_fops =
{
.unlocked_ioctl = my_ioctl, error is here. I can not fix this.
};
Note: please ignore all my print_k.
Please, help me fix this. My thanks to all of you.
Here is my code :
static long my_ioctl(struct file *f,unsigned int cm,unsigned long arg[b])
{
int re;
unsigned long arg[3];
switch (cm)
{
case H_ADD:
arg[2] = arg[0] + arg[1];
print_k("Driver:Calculating is complete,Result = %d \n",arg[2]);
break;
case H_SUB:
print_k ("Driver: Start ...\n");
arg[2] = arg[0] - arg[1];
print_k("Driver:Calculating is complete,Result = %d \n",arg[2]);
break;
case H_MULL:
print_k ("Driver: Start ...\n");
arg[2] = arg[0] * arg[1];
print_k("Driver:Calculating is complete,Result = %d \n",arg[2]);
break;
case H_DIV:
print_k ("Driver: Start ...\n");
arg[2] = arg[0] / arg[1];
print_k("Driver:Calculating is complete,Result = %d \n",arg[2]);
break;
default:
print_k ("Driver: I don't have this operation!\n");
re = -Er;
break;
}
return re;
}
static struct file_operations my_fops =
{
.unlocked_ioctl = my_ioctl,
};
The third argument unsigned long arg[b] in the function prototype is dubious. It should be simply unsigned long arg even if it's supposed to be a pointer. It's easy to cast it to the type of interest within the function body.
..the optional arg argument is passed in the form of an unsigned long, regardless of whether it was given by the user as an integer or a pointer.
( Linux Device Drivers 3, Chapter 6, Section 1 )
Also, it's wrong to declare a variable within the function body which has the same name as one of the arguments. Please choose another name for unsigned long arg[3];.

Where could I find the code of "sched_getcpu()"

Recently I'm using the function sched_getcpu() from the header file sched.h on Linux.
However, I'm wondering where could I find the source code of this function?
Thanks.
Under Linux, the sched_getcpu() function is a glibc wrapper to sys_getcpu() system call, which is architecture specific.
For the x86_64 architecture, it is defined under arch/x86/include/asm/vgtod.h as __getcpu() (tree 4.x):
#ifdef CONFIG_X86_64
#define VGETCPU_CPU_MASK 0xfff
static inline unsigned int __getcpu(void)
{
unsigned int p;
/*
* Load per CPU data from GDT. LSL is faster than RDTSCP and
* works on all CPUs. This is volatile so that it orders
* correctly wrt barrier() and to keep gcc from cleverly
* hoisting it out of the calling function.
*/
asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
return p;
}
#endif /* CONFIG_X86_64 */
Being this function called by __vdso_getcpu() declared in arch/entry/vdso/vgetcpu.c:
notrace long
__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
{
unsigned int p;
p = __getcpu();
if (cpu)
*cpu = p & VGETCPU_CPU_MASK;
if (node)
*node = p >> 12;
return 0;
}
(See vDSO for details regarding what vdso prefix is).
EDIT 1: (in reply to arm code location)
ARM code location
It can be found in the arch/arm/include/asm/thread_info.h file:
static inline struct thread_info *current_thread_info(void)
{
return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1));
}
This function is used by raw_smp_processor_id() that is defined in the file arch/arm/include/asm/smp.h as:
#define raw_smp_processor_id() (current_thread_info()->cpu)
And it's called by getcpu system call declared in the file kernel/sys.c:
SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, struct getcpu_cache __user *, unused)
{
int err = 0;
int cpu = raw_smp_processor_id();
if (cpup)
err |= put_user(cpu, cpup);
if (nodep)
err |= put_user(cpu_to_node(cpu), nodep);
return err ? -EFAULT : 0;
}

impossible constraint in 'asm' error

I'm trying to cross-compile a c++ file with arm-linux-gnueabi-g++.:
make CROSS_COMPILE=arm-linux-gnueabi- all
But an error occurs:
arm-linux-gnueabi-g++ -O2 -c -oa32.o PMCTestA.cpp
In file included from PMCTest.h:54:0,
from PMCTestA.cpp:24:
PMCTestLinux.h: In member function ‘void CCounters::GetProcessorVendor()’:
PMCTestLinux.h:63:73: error: impossible constraint in ‘asm’
make: *** [a32.o] Error 1
And here is part of the code in PMCTestLinux.h from row 61:
static void Cpuid (int Output[4], int aa) {
int a, b, c, d;
__asm("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(aa),"c"(0) : );
Output[0] = a;
Output[1] = b;
Output[2] = c;
Output[3] = d;
}
static inline void Serialize () {
// serialize CPU
__asm__ __volatile__ ( "xorl %%eax, %%eax \n cpuid " : : : "%eax","%ebx","%ecx","%edx" );
}
static inline int Readtsc() {
// read time stamp counter
int r;
__asm__ __volatile__ ( "rdtsc" : "=a"(r) : : "%edx");
return r;
}
static inline int Readpmc(int nPerfCtr) {
// read performance monitor counter number nPerfCtr
int r;
__asm__ __volatile__ ( "rdpmc" : "=a"(r) : "c"(nPerfCtr) : "%edx");
return r;
}
Does anyone know something about this error? I'm not sure if the problem is about the compiler. My system is Ubuntu 10.04 and the version of arm-linux-gnueabi-g++ is 4.7.3

Opening sockets to the Xserver directly

I'm looking to understand how Linux Desktop Environments work with Xserver. I was reading that most window managers don't open sockets directly, instead they use either Xlib bindings for which ever language the WM is being written or you can use higher level bindings XCB; but i would like to know What are the advantages to opening a socket directly to the Xserver?
I'm not going to tell you the advantages, but I'm going to tell you how to do it.
Some time ago I found an exampe of someone this, and I can't find it anymore, but here's more or less his code. It's quite interesting to know what's going on under the hood of client libraries like XCB.
In order to send a request to the X server, you need:
a socket connection to the X server
the opcode of the request
data associated to the request
The API to open a socket, create a graphics context, create a window, and map a window can look something like:
x11_connection_t connection = {0};
x11_init_connection(&connection);
x11_state_t state;
state.socket_fd = connection.socket_fd;
state.id_base = connection.setup->id_base;
state.root_window = connection.root[0].window_id;
state.root_visual = connection.root[0].visual_id;
state.root_depth = connection.root[0].depth;
state.gcontext = x11_init_gc(&state, X11_GC_GRAPHICS_EXPOSURES, (u32[]){X11_EXPOSURES_NOT_ALLOWED});
state.window = x11_init_window(&state, 0,0, WIDTH,HEIGHT, state.root_window, state.root_visual,
X11_CW_BACK_PIXEL | X11_CW_EVENT_MASK,
(u32[]){XCB_RGB_BLUE, X11_EVENT_MASK_KEY_PRESS | X11_EVENT_MASK_POINTER_MOTION}); // X11_EVENT_MASK_KEY_PRESS | X11_EVENT_MASK_POINTER_MOTION | X11_EVENT_MASK_STRUCTURE_NOTIFY | X11_EVENT_MASK_EXPOSURE
x11_map_window(&state, state.window);
But first we need to implement it.
For illustration, here are the first thirteen X protocol opcodes:
#define X11_OPCODE_CREATE_WINDOW 1
#define X11_OPCODE_CHANGE_WINDOW_ATTRIBUTES 2
#define X11_OPCODE_GET_WINDOW_ATTRIBUTES 3
#define X11_OPCODE_DESTROY_WINDOW 4
#define X11_OPCODE_DESTROY_SUBWINDOWS 5
#define X11_OPCODE_CHANGE_SAVE_SET 6
#define X11_OPCODE_REPARENT_WINDOW 7
#define X11_OPCODE_MAP_WINDOW 8
#define X11_OPCODE_MAP_SUBWINDOWS 9
#define X11_OPCODE_UNMAP_WINDOW 10
#define X11_OPCODE_UNMAP_SUBWINDOWS 11
#define X11_OPCODE_CONFIGURE_WINDOW 12
#define X11_OPCODE_CIRCULATE_WINDOW 13
You can open the socket with a function like the following,
int x11_init_socket(){
int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); // Create the socket!
struct sockaddr_un serv_addr = {0};
serv_addr.sun_family = AF_UNIX;
strcpy(serv_addr.sun_path, "/tmp/.X11-unix/X0");
int srv_len = sizeof(struct sockaddr_un);
connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
return socket_fd;
}
Then you need the handshake,
int x11_init_connection(x11_connection_t* connection){
connection->socket_fd = x11_init_socket();
x11_connection_request_t request = {0};
request.order = 'l'; // Little endian!
request.major = 11;
request.minor = 0; // Version 11.0
write(connection->socket_fd, &request, sizeof(x11_connection_request_t)); // Send request
read(connection->socket_fd, &connection->header, sizeof(x11_connection_reply_t)); // Read reply header
if(connection->header.success == 0) return connection->header.success; // Error handling!
connection->setup = sbrk(connection->header.length * 4); // Allocate memory for remainder of data
read(connection->socket_fd, connection->setup, connection->header.length * 4); // Read remainder of data
void* p = ((void*)connection->setup);
p += sizeof(x11_connection_setup_t) + connection->setup->vendor_length; // Ignore the vendor
connection->format = p; p += sizeof(x11_pixmap_format_t) * connection->setup->formats; // Align struct with format sections. Move pointer to end of section
connection->root = p; p += sizeof(x11_root_t) * connection->setup->roots; // Align struct with root section(s). Move pointer to end of section
connection->depth = p; p += sizeof(x11_depth_t); // Align depth struct with first depth section. Move pointer to end of section
connection->visual = p; // Align visual with first visual for first depth
return connection->header.success;
}
and a bunch of data structures that the X server likes:
typedef struct{
u8 order;
u8 pad1;
u16 major, minor;
u16 auth_proto, auth_data;
u16 pad2;
}x11_connection_request_t;
typedef struct{
u8 success;
u8 pad1;
u16 major, minor;
u16 length;
}x11_connection_reply_t;
typedef struct{
u32 release;
u32 id_base, id_mask;
u32 motion_buffer_size;
u16 vendor_length;
u16 request_max;
u8 roots;
u8 formats;
u8 image_order;
u8 bitmap_order;
u8 scanline_unit, scanline_pad;
u8 keycode_min, keycode_max;
u32 pad;
}x11_connection_setup_t;
typedef struct{
u8 depth;
u8 bpp;
u8 scanline_pad;
u8 pad1;
u32 pad2;
}x11_pixmap_format_t;
typedef struct{
u32 window_id;
u32 colormap;
u32 white, black;
u32 input_mask;
u16 width, height;
u16 width_mm, height_mm;
u16 maps_min, maps_max;
u32 visual_id;
u8 backing_store;
u8 save_unders;
u8 depth;
u8 depths;
}x11_root_t;
typedef struct{
u8 depth;
u8 pad1;
u16 visuals;
u32 pad2;
}x11_depth_t;
typedef struct{
u8 group;
u8 bits;
u16 colormap_entries;
u32 mask_red, mask_green, mask_blue;
u32 pad;
}x11_visual_t;
typedef struct{
u8 response_type; /**< Type of the response */
u8 pad0; /**< Padding */
u16 sequence; /**< Sequence number */
u32 pad[7]; /**< Padding */
u32 full_sequence; /**< full sequence */
}x11_generic_event_t;
typedef struct{
u8 success;
u8 code;
u16 seq;
u32 id;
u16 op_major;
u8 op_minor;
u8 pad[21];
}x11_error_t;
typedef struct{
int socket_fd;
x11_connection_reply_t header;
x11_connection_setup_t* setup;
x11_pixmap_format_t* format;
x11_root_t* root;
x11_depth_t* depth;
x11_visual_t* visual;
}x11_connection_t;
typedef struct{
int socket_fd;
u32 id_base; // We'll use this to generate 32-bit identifiers!
u32 root_window;
u32 root_visual;
u8 root_depth;
u32 window;
u32 gcontext;
}x11_state_t;
You also need a function a function to generate 32-bit identifiers:
u32 x11_generate_id(x11_connection_t* connection){
static u32 id = 0;
return (id++ | connection->setup->id_base);
}
Finally, you need the actual functions that assemble the packets with the requests. The following are helper functions to send X11_OPCODE_CREATE_GC, X11_OPCODE_CREATE_WINDOW, X11_OPCODE_MAP_WINDOW, and X11_OPCODE_PUT_IMAGE.
#define X11_NONE 0x00000000L // X11_NONE is the universal null resource or null atom parameter value for many core X requests
#define X11_COPY_FROM_PARENT 0x00000000L // X11_COPY_FROM_PARENT can be used for many xcb_create_window parameters
#define X11_CURRENT_TIME 0x00000000L // X11_CURRENT_TIME can be used in most requests that take an xcb_timestamp_t
#define X11_NO_SYMBOL 0x00000000L // X11_NO_SYMBOL fills in unused entries in xcb_keysym_t tables
enum x11_exposures_t{
X11_EXPOSURES_NOT_ALLOWED = 0,
X11_EXPOSURES_ALLOWED = 1,
X11_EXPOSURES_DEFAULT = 2
};
enum x11_gc_t{
X11_GC_FUNCTION = 1<<0,
X11_GC_PLANE_MASK = 1<<1,
X11_GC_FOREGROUND = 1<<2,
X11_GC_BACKGROUND = 1<<3,
X11_GC_LINE_WIDTH = 1<<4,
X11_GC_LINE_STYLE = 1<<5,
X11_GC_CAP_STYLE = 1<<6,
X11_GC_JOIN_STYLE = 1<<7,
X11_GC_FILL_STYLE = 1<<8,
X11_GC_FILL_RULE = 1<<9,
X11_GC_TILE = 1<<10,
X11_GC_STIPPLE = 1<<11,
X11_GC_TILE_STIPPLE_ORIGIN_X = 1<<12,
X11_GC_TILE_STIPPLE_ORIGIN_Y = 1<<13,
X11_GC_FONT = 1<<14,
X11_GC_SUBWINDOW_MODE = 1<<15,
X11_GC_GRAPHICS_EXPOSURES = 1<<16,
X11_GC_CLIP_ORIGIN_X = 1<<17,
X11_GC_CLIP_ORIGIN_Y = 1<<18,
X11_GC_CLIP_MASK = 1<<19,
X11_GC_DASH_OFFSET = 1<<20,
X11_GC_DASH_LIST = 1<<21,
X11_GC_ARC_MODE = 1<<22,
};
u32 x11_init_gc(x11_state_t* state, u32 value_mask, u32* value_list){
u32 gcontext_id = x11_generate_id(state);
u16 flag_count = popcnt(value_mask);
u16 length = 4 + flag_count;
u32* packet = sbrk(length * 4);
packet[0] = X11_OPCODE_CREATE_GC | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = gcontext_id;
packet[2] = state->root_window;
packet[3] = value_mask;
for(int i=0; i < flag_count; ++i)
packet[4 + i] = value_list[i];
write(state->socket_fd, packet, length * 4);
sbrk(-(length * 4));
return gcontext_id;
}
enum x11_cw_t{
X11_CW_BACK_PIXMAP = 1<<0,
X11_CW_BACK_PIXEL = 1<<1,
X11_CW_BORDER_PIXMAP = 1<<2,
X11_CW_BORDER_PIXEL = 1<<3,
X11_CW_BIT_GRAVITY = 1<<4,
X11_CW_WIN_GRAVITY = 1<<5,
X11_CW_BACKING_STORE = 1<<6,
X11_CW_BACKING_PLANES = 1<<7,
X11_CW_BACKING_PIXEL = 1<<8,
X11_CW_OVERRIDE_REDIRECT = 1<<9,
X11_CW_SAVE_UNDER = 1<<10,
X11_CW_EVENT_MASK = 1<<11,
X11_CW_DONT_PROPAGATE = 1<<12,
X11_CW_COLORMAP = 1<<13,
X11_CW_CURSOR = 1<<14
};
enum x11_event_mask_t{
X11_EVENT_MASK_NO_EVENT = 0,
X11_EVENT_MASK_KEY_PRESS = 1<<0, // 0x00000001
X11_EVENT_MASK_KEY_RELEASE = 1<<1, // 0x00000002
X11_EVENT_MASK_BUTTON_PRESS = 1<<2, // 0x00000004
X11_EVENT_MASK_BUTTON_RELEASE = 1<<3, // 0x00000008
X11_EVENT_MASK_ENTER_WINDOW = 1<<4, // 0x00000010
X11_EVENT_MASK_LEAVE_WINDOW = 1<<5, // 0x00000020
X11_EVENT_MASK_POINTER_MOTION = 1<<6, // 0x00000040
X11_EVENT_MASK_POINTER_MOTION_HINT = 1<<7, // 0x00000080
X11_EVENT_MASK_BUTTON_1_MOTION = 1<<8, // 0x00000100
X11_EVENT_MASK_BUTTON_2_MOTION = 1<<9, // 0x00000200
X11_EVENT_MASK_BUTTON_3_MOTION = 1<<10, // 0x00000400
X11_EVENT_MASK_BUTTON_4_MOTION = 1<<11, // 0x00000800
X11_EVENT_MASK_BUTTON_5_MOTION = 1<<12, // 0x00001000
X11_EVENT_MASK_BUTTON_MOTION = 1<<13, // 0x00002000
X11_EVENT_MASK_KEYMAP_STATE = 1<<14, // 0x00004000
X11_EVENT_MASK_EXPOSURE = 1<<15, // 0x00008000
X11_EVENT_MASK_VISIBILITY_CHANGE = 1<<16, // 0x00010000
X11_EVENT_MASK_STRUCTURE_NOTIFY = 1<<17, // 0x00020000
X11_EVENT_MASK_RESIZE_REDIRECT = 1<<18, // 0x00040000
X11_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 1<<19, // 0x00080000
X11_EVENT_MASK_SUBSTRUCTURE_REDIRECT = 1<<20, // 0x00100000
X11_EVENT_MASK_FOCUS_CHANGE = 1<<21, // 0x00200000
X11_EVENT_MASK_PROPERTY_CHANGE = 1<<22, // 0x00400000
X11_EVENT_MASK_COLOR_MAP_CHANGE = 1<<23, // 0x00800000
X11_EVENT_MASK_OWNER_GRAB_BUTTON = 1<<24 // 0x01000000
};
#define X11_DEFAULT_BORDER 0
#define X11_DEFAULT_GROUP 0
u32 x11_init_window(x11_state_t* state, u16 x, u16 y, u16 w, u16 h, u32 window_parent, u32 visual, u32 value_mask, u32* value_list){
u32 window_id = x11_generate_id(state);
u16 flag_count = popcnt(value_mask);
u16 length = 8 + flag_count;
u32* packet = sbrk(length * 4);
packet[0] = X11_OPCODE_CREATE_WINDOW | length<<16; // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = window_id;
packet[2] = window_parent;
packet[3] = x | (y<<16);
packet[4] = w | (h<<16);
packet[5] = (X11_DEFAULT_BORDER<<16) | X11_DEFAULT_GROUP;
packet[6] = visual;
packet[7] = value_mask;
for(int i=0;i < flag_count; ++i)
packet[8 + i] = value_list[i];
write(state->socket_fd, packet, length * 4);
sbrk(-(length * 4));
return window_id;
}
void x11_map_window(x11_state_t* state, u32 window_id){
int const length = 2;
u32 packet[length];
packet[0] = X11_OPCODE_MAP_WINDOW | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = window_id;
write(state->socket_fd, packet, 8);
}
enum x11_image_format_t{
X11_IMAGE_FORMAT_XY_BITMAP = 0,
X11_IMAGE_FORMAT_XY_PIXMAP = 1,
X11_IMAGE_FORMAT_Z_PIXMAP = 2
};
void x11_put_img(x11_state_t* state, u16 x, u16 y, u32* data){
u32 packet[6];
u16 const length = ((state->tile_width * state->tile_height)) + 6;
packet[0] = X11_OPCODE_PUT_IMAGE | (X11_IMAGE_FORMAT_Z_PIXMAP<<8) | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = state->window;
packet[2] = state->gcontext;
packet[3] = state->tile_width | (state->tile_height<<16);
packet[4] = x | (y<<16);
packet[5] = state->root_depth<<8;
write(state->socket_fd, packet, 24);
write(state->socket_fd, data, state->tile_width * state->tile_height * 4);
}
I've done it with node/javascript ( https://github.com/sidorares/node-x11/ )
It's not as scary as it seems, and for some particular tasks might work better than xlib ( non-trivial parallelism or resource dependencies or indirect glx ), but probably most value in this is educational. If you just want some work done there is probably solution available and you don't need to reinvent the wheel
Starting point would be x11 protocol documentation: https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html
The question should rather be "What are the advantages of using Xlib instead of a graphical toolkit like gtk"?
Even to master Xlib, you have to spent months or years! It's so intricate that almost every app that has graphical content to display uses a toolkit instead.
Using a plain socket means speaking the X11 protocol directly, which means you would end up recreating Xlib (no, you wouldn't finish!)
As an analogy, plain socket ~ machine code, xlib ~ assembly code, toolkit ~ higher level language. (notwithstanding that xlib does a little maintenance for you, but I guess it's rather neglectable)

Resources