jumper149 / blugon

simple and configurable Blue Light Filter for X
Apache License 2.0
146 stars 6 forks source link

Blugon's filter keeps reverting #25

Open apurbapokharel opened 2 years ago

apurbapokharel commented 2 years ago

I use sxhkd and use key binding for blugon blugon --setcurrent="+100" and blugon --setcurrent="-100"

The command works initially but after a short moment it reverts back and I have to use the command again via bindings. Any help on how to make the command work permanently would be appreciated.

jumper149 commented 2 years ago

--setcurrent, only sets the gamma value once and then exits. You probably have another program running, that periodically updates that gamma value.

That program could either be another instance of blugon or maybe something else. I personally only noticed it with some programs under wine, but pretty much any program could talk to with your X-server.

apurbapokharel commented 2 years ago

Is there anyway to find out what is causing it to revert, specifically?

correabuscar commented 2 years ago

Is there anyway to find out what is causing it to revert, specifically?

Yes, you can hook the X function(s) that are being used to set the gamma and thus detect and print or log the program that's calling them. Apparently this is called "Function interposition - it is the concept of replacing calls to functions in dynamic libraries with calls to user-defined wrapper functions." (quote slightly modified)

You'd have to use LD_PRELOAD when starting X, so that any processes that X spawns will have those functions hooked, so for example if you log into console (ie. TERM=linux), you then manually startx like so: $ LD_PRELOAD=/must/be/absolute/path/to/libprog2.so startx where libprog2.so is made by gcc -D_FORTIFY_SOURCE=2 -O1 -rdynamic -ggdb -shared -ldl -fPIC prog2.c -o libprog2.so and prog2.c has these contents(it looks ugly because it was fun play):

//based on, src: https://www.opensourceforu.com/2011/08/lets-hook-a-library-function/
#define NOSTACK_internal //define to not print stacktraces! comment out to get stacktraces for the calls to the hooked functions!
#define LOGFILE_internal "/tmp/gamma_setters.log" //comment out to use stderr !

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>                               /* header required for dlsym() */
#include <stdbool.h>

// backtrace code src: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
// backtrace code compile with: gcc -D_FORTIFY_SOURCE=2 backtrace.c -ggdb -O1 -rdynamic
#include <execinfo.h>
//#include <stdio.h>
#include <stdlib.h>

#include <X11/extensions/Xrandr.h> //for XRRSetCrtcGamma's args' types! TODO; include only the needed .h or even just copy/paste the type?(hard due to any ifdefs when defining types, I imagine) note that headers aren't needed at all, just the function signature(and the types it references) but can do this without including headers.

#include <unistd.h> //page size, close()
#include <fcntl.h> //open()

#include <X11/extensions/xf86vmode.h>

//TODO: there are more gamma setting functions to hook!

#include <xcb/randr.h> // xcb_randr_set_crtc_gamma_checked(), xcb_randr_crtc_t
#include <xcb/xcb.h> // xcb_void_cookie_t

#ifdef LOGFILE_internal
//use log file
#define LE_OUT_HANDLE_internal logf
#define FCLOSE_internal \
      if (NULL!=LE_OUT_HANDLE_internal) {\
        fclose(LE_OUT_HANDLE_internal); \
        LE_OUT_HANDLE_internal=NULL; \
      }

#define FOPENLOG_internal \
      FILE *LE_OUT_HANDLE_internal = fopen(LOGFILE_internal,"a"); \
      if (NULL==LE_OUT_HANDLE_internal){ \
        LE_OUT_HANDLE_internal=stderr; \
      }
#else
//if not defined, use standard error output
#define LE_OUT_HANDLE_internal stderr
#define FCLOSE_internal
#define FOPENLOG_internal
#endif
//extern void *__libc_dlsym (void *, const char *);
/* lcheck() is for memory leak check; its code is not shown
 here */
//void lcheck(void);
void __internalshie_print_trace(void); //renamed to prevent overloading any actual such function!
void __internalshie_show_current_process(const char *func_name); //renamed to prevent overloading any actual such function!

//function xcb_randr_set_crtc_gamma_checked is used by x11-misc/redshift: /usr/bin/redshift -m randr
xcb_void_cookie_t xcb_randr_set_crtc_gamma_checked (xcb_connection_t *c, xcb_randr_crtc_t  crtc, uint16_t size, const uint16_t *red, const uint16_t *green, const uint16_t *blue) {
  static xcb_void_cookie_t (*my_xcb_randr_set_crtc_gamma_checked)(xcb_connection_t *c, xcb_randr_crtc_t  crtc, uint16_t          size, const uint16_t   *red, const uint16_t     *green, const uint16_t   *blue)=NULL;
  if (NULL==my_xcb_randr_set_crtc_gamma_checked) {
    my_xcb_randr_set_crtc_gamma_checked=dlsym(RTLD_NEXT, "xcb_randr_set_crtc_gamma_checked");
    if (NULL==my_xcb_randr_set_crtc_gamma_checked) {
      FOPENLOG_internal
#ifndef LOGFILE_internal
      fflush(stdout);
#endif
      fprintf(LE_OUT_HANDLE_internal,"!! EPIC fail for function '%s'.\n",__func__);
      fflush(LE_OUT_HANDLE_internal);
      FCLOSE_internal
      static xcb_void_cookie_t fixme; //FIXME:
      return fixme;
    }
  }
  __internalshie_show_current_process(__func__);
  __internalshie_print_trace();
  return my_xcb_randr_set_crtc_gamma_checked(c,crtc,size,red,green,blue);
}
//function drmModeCrtcSetGamma is used by x11-misc/redshift: /usr/bin/redshift -m drm
int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue){
  static int (*my_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue)=NULL;
  if (NULL==my_drmModeCrtcSetGamma) {
    my_drmModeCrtcSetGamma=dlsym(RTLD_NEXT, "drmModeCrtcSetGamma");
    if (NULL==my_drmModeCrtcSetGamma) {
      FOPENLOG_internal
#ifndef LOGFILE_internal
      fflush(stdout);
#endif
      fprintf(LE_OUT_HANDLE_internal,"!! EPIC fail for function '%s'.\n",__func__);
      fflush(LE_OUT_HANDLE_internal);
      FCLOSE_internal
      return 0; //FIXME:
    }
  }
  __internalshie_show_current_process(__func__);
  __internalshie_print_trace();
  return my_drmModeCrtcSetGamma(fd,crtc_id,size,red,green,blue);
}
//function XF86VidModeSetGammaRamp from xf86vmode.h it's used by x11-misc/redshift: /usr/bin/redshift -m vidmode
Bool XF86VidModeSetGammaRamp(
      Display*                    dpy,
      int                         screen,
      int       size,
      unsigned short*             red_array,
      unsigned short*             green_array,
      unsigned short*             blue_array
  ) {
  static Bool (*my_XF86VidModeSetGammaRamp)(Display* dpy, int screen, int size, unsigned short*, unsigned short*,unsigned short*)=NULL;
  if (NULL==my_XF86VidModeSetGammaRamp) {
    my_XF86VidModeSetGammaRamp=dlsym(RTLD_NEXT, "XF86VidModeSetGammaRamp");
    if (NULL==my_XF86VidModeSetGammaRamp) {
      FOPENLOG_internal
#ifndef LOGFILE_internal
      fflush(stdout);
#endif
      fprintf(LE_OUT_HANDLE_internal,"!! EPIC fail for function '%s'.\n",__func__);
      fflush(LE_OUT_HANDLE_internal);
      FCLOSE_internal
      return false;
    }
  }
  __internalshie_show_current_process(__func__);
  __internalshie_print_trace();
  return my_XF86VidModeSetGammaRamp(dpy,screen,size,red_array,green_array,blue_array);
}

//typedef struct {
//    float red;            /* Red Gamma value */
//    float green;        /* Green Gamma value */
//    float blue;            /* Blue Gamma value */
//} XF86VidModeGamma;
//function used by x11-apps/xgamma: /usr/bin/xgamma
Bool XF86VidModeSetGamma(Display *display, int screen, XF86VidModeGamma *Gamma) {
  static Bool (*my_XF86VidModeSetGamma)(Display *display, int screen, XF86VidModeGamma *Gamma)=NULL;
  if (NULL==my_XF86VidModeSetGamma) {
    my_XF86VidModeSetGamma=dlsym(RTLD_NEXT, "XF86VidModeSetGamma");
    if (NULL==my_XF86VidModeSetGamma) {
      FOPENLOG_internal
#ifndef LOGFILE_internal
      fflush(stdout);
#endif
      fprintf(LE_OUT_HANDLE_internal,"!! EPIC fail for function '%s'.\n",__func__);
      fflush(LE_OUT_HANDLE_internal);
      FCLOSE_internal
      return false;
    }
  }
  __internalshie_show_current_process(__func__);
  __internalshie_print_trace();
  return my_XF86VidModeSetGamma(display,screen,Gamma);
}

//function used by secote, at least. https://github.com/temporaryrespite/secote
void XRRSetCrtcGamma (Display *dpy, RRCrtc crtc, XRRCrtcGamma *gamma) {
  static void (*my_XRRSetCrtcGamma)(Display *dpy, RRCrtc crtc, XRRCrtcGamma *gamma)=NULL;
  static bool already_in=false; //was only needed for when hooking malloc() to prevent recursion! for XRRSetCrtcGamma isn't needed! FIXME: remove
  if (!my_XRRSetCrtcGamma) {
    already_in=true;
    my_XRRSetCrtcGamma=dlsym(RTLD_NEXT, "XRRSetCrtcGamma");
    already_in=false;
    if (NULL==my_XRRSetCrtcGamma) {
      already_in=true;
      FOPENLOG_internal
#ifndef LOGFILE_internal
      fflush(stdout);
#endif
      fprintf(LE_OUT_HANDLE_internal,"!! EPIC fail for function '%s'.\n",__func__);
      fflush(LE_OUT_HANDLE_internal);
      FCLOSE_internal
      already_in=false;
      return;
    }
  }
  if (!already_in) {
    already_in=true;
    __internalshie_show_current_process(__func__);
    __internalshie_print_trace();
    already_in=false;
  }
  my_XRRSetCrtcGamma(dpy,crtc,gamma);
  return;
}

//void* malloc(size_t size)
//{
//  static void* (*my_malloc)(size_t) = NULL;
//  static bool already_in=false;
//  if (!my_malloc) {
//    already_in=true;
//    my_malloc = dlsym(RTLD_NEXT, "malloc");  /* returns the object reference for malloc */
//    //my_malloc = __libc_dlsym(RTLD_NEXT, "malloc");  /* returns the object reference for malloc */
//    already_in=false;
//    if (NULL==my_malloc) {
//      already_in=true;
//      printf("!! EPIC fail...\n");
//      already_in=false;
//      return NULL;
//    }
//    //my_malloc = (void * (*)(size_t))dlsym(RTLD_NEXT, "malloc");  /* returns the object reference for malloc */
//  }
//  if (!already_in) {
//    already_in=true;
//    printf("!! inside shared object...\n");
//    fflush(stdout);
//    already_in=false;
//  }
//  void *p = my_malloc(size);               /* call malloc() using function pointer my_malloc */  
//  if (!already_in) {
//    already_in=true;
//    printf("!! malloc(%ld) = %p\n", size, p);
//    fflush(stdout);
//    __internalshie_print_trace();
//    //lcheck();                                /* calling do_your_stuff function */
//    printf("!! returning from shared object...\n");
//    fflush(stdout);
//    already_in=false;
//  }
//  //already_in=false; // stack trace recursion was only needed because this was uncommented!
//  return p;
//}
//void lcheck(void)
//{
//  printf("!! displaying memory leaks...\n");
//  fflush(stdout);
//  /* do required stuff here */
//}

//used sources for this function:
//https://stackoverflow.com/questions/24127416/parsing-command-line-arguments-from-proc-pid-cmdline/24128544#24128544
//https://stackoverflow.com/questions/1563168/example-of-realpath-function-in-c/1563237#1563237
void __internalshie_show_current_process(const char *func_name) {
  FOPENLOG_internal
  {
    char *rp=realpath("/proc/self/exe", NULL/*aka malloc() for me*/);
    if (NULL != rp) {
      fprintf(LE_OUT_HANDLE_internal,"!! The program '%s' was called as: ",rp);
      free(rp);
    } else {
      perror("!! realpath");//FIXME: this should use LE_OUT_HANDLE_internal ie. the log file or stderr, now using only stderr!
    }
  }
  const long PAGESIZE = sysconf(_SC_PAGESIZE); //ie. 4096, run at prompt: $ getconf PAGESIZE  (getconf is part of sys-libs/glibc, on Gentoo)
  const long BUFSIZE = PAGESIZE;
  unsigned char buffer[BUFSIZE];//FIXME: hmm, using 4k of stack?
  int fd = open("/proc/self/cmdline", O_RDONLY);
  int nbytesread = read(fd, buffer, BUFSIZE);
    unsigned char *end = buffer + nbytesread;
  //fprintf(LE_OUT_HANDLE_internal,"!! ");
    for (unsigned char *p = buffer; p < end; /**/)
    {
        fprintf(LE_OUT_HANDLE_internal,"'%s' ",p);
        while (*p++); // skip until start of next 0-terminated section
    }
  fprintf(LE_OUT_HANDLE_internal,"and is using function '%s'\n",func_name);//don't erase last space char and add new line after this text
  fflush(LE_OUT_HANDLE_internal);
  FCLOSE_internal
  close(fd);
}

/* Obtain a backtrace and print it to stdout. */
void
__internalshie_print_trace (void)
{
#if defined NOSTACK_internal
  return;
#endif
  FOPENLOG_internal
#define MAX_LINES_IN_STACKDUMP 100
  //static bool intrace=false;
  void *array[MAX_LINES_IN_STACKDUMP];
  size_t size;
  char **strings;
  size_t i;

//  if (!intrace) {
//    intrace=true;

    size = backtrace (array, MAX_LINES_IN_STACKDUMP);
    strings = backtrace_symbols (array, size);

    fflush(stdout);
    fprintf (LE_OUT_HANDLE_internal,"!! Obtained %zd stack frames.\n", size);
    fflush(LE_OUT_HANDLE_internal);

    for (i = 0; i < size; i++)
      fprintf (LE_OUT_HANDLE_internal,"!! %s\n", strings[i]);

    fflush(LE_OUT_HANDLE_internal);
    free (strings);
//    intrace=false;
//  } else {
//    printf ("!! stacktrace recursion prevented.\n");
//    fflush(stdout);
//  }
  FCLOSE_internal
}

But if you don't hook startx, you can just try it like this (but it's usless for what you wanted):

gcc -D_FORTIFY_SOURCE=2 -O1 -rdynamic -ggdb -shared -ldl -fPIC prog2.c -o libprog2.so                                                                             

if test -e "$(which secote)"; then                                                                                                                                
  LD_PRELOAD="$(realpath -- libprog2.so)" secote 3000                                                                                                             
fi                                                                                                                                                                

if test -e "$(which xgamma)"; then                                                                                                                                
  LD_PRELOAD="$(realpath -- libprog2.so)" xgamma -gamma 1.0                                                                                                       
  LD_PRELOAD="$(realpath -- libprog2.so)" xgamma -rgamma 1.0 -ggamma 0.6949030005552019 -bgamma 0.4310480202110507                                                
  LD_PRELOAD="$(realpath -- libprog2.so)" xgamma -gamma 1.0                                                                                                       
fi                                                                                                                                                                

if test -e "$(which redshift)"; then                                                                                                                              
  LD_PRELOAD="$(realpath -- libprog2.so)" redshift -P -O 3000 -m vidmode                                                                                          
  LD_PRELOAD="$(realpath -- libprog2.so)" redshift -P -O 3000 -m drm                                                                                              
  LD_PRELOAD="$(realpath -- libprog2.so)" redshift -P -O 3000 -m randr                                                                                            
fi                                                                                                                                                                

and then the file /tmp/gamma_setters.log would have these contents:

!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-gamma' '1.0' and is using function 'XF86VidModeSetGamma'
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-rgamma' '1.0' '-ggamma' '0.6949030005552019' '-bgamma' '0.4310480202110507' and is using function 'XF86VidModeSetGamma'
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-gamma' '1.0' and is using function 'XF86VidModeSetGamma'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'vidmode' and is using function 'XF86VidModeSetGammaRamp'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'

(but if you hooked startx with LD_PRELOAD, then you don't need the above LD_PRELOAD(s), that's the whole point, any subprocess(try ps ax --forest) will be caught)

If you comment out the first define, you can get stacktraces too(kinda useless unless programs were compiled with -ggdb I guess):

!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7f69208f63cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XRRSetCrtcGamma+0x6b) [0x7f69208f684d]
!! secote(+0x1288) [0x55f385adf288]
!! /lib64/libc.so.6(+0x29386) [0x7f69204d6386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7f69204d6447]
!! secote(+0x142a) [0x55f385adf42a]
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7f69208f63cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XRRSetCrtcGamma+0x6b) [0x7f69208f684d]
!! secote(+0x1288) [0x55f385adf288]
!! /lib64/libc.so.6(+0x29386) [0x7f69204d6386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7f69204d6447]
!! secote(+0x142a) [0x55f385adf42a]
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7f69208f63cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XRRSetCrtcGamma+0x6b) [0x7f69208f684d]
!! secote(+0x1288) [0x55f385adf288]
!! /lib64/libc.so.6(+0x29386) [0x7f69204d6386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7f69204d6447]
!! secote(+0x142a) [0x55f385adf42a]
!! The program '/swcode/bin.append/secote' was called as: 'secote' '3000' and is using function 'XRRSetCrtcGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7f69208f63cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XRRSetCrtcGamma+0x6b) [0x7f69208f684d]
!! secote(+0x1288) [0x55f385adf288]
!! /lib64/libc.so.6(+0x29386) [0x7f69204d6386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7f69204d6447]
!! secote(+0x142a) [0x55f385adf42a]
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-gamma' '1.0' and is using function 'XF86VidModeSetGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7dfbfb61c3cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XF86VidModeSetGamma+0x27) [0x7dfbfb61c752]
!! xgamma(main+0x523) [0x61c500f7e673]
!! /lib64/libc.so.6(+0x29386) [0x7dfbfb2db386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7dfbfb2db447]
!! xgamma(_start+0x21) [0x61c500f7e971]
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-rgamma' '1.0' '-ggamma' '0.6949030005552019' '-bgamma' '0.4310480202110507' and is using function 'XF86VidModeSetGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7e9dc4f643cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XF86VidModeSetGamma+0x27) [0x7e9dc4f64752]
!! xgamma(main+0x523) [0x58c0f3a37673]
!! /lib64/libc.so.6(+0x29386) [0x7e9dc4c23386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7e9dc4c23447]
!! xgamma(_start+0x21) [0x58c0f3a37971]
!! The program '/usr/bin/xgamma' was called as: 'xgamma' '-gamma' '1.0' and is using function 'XF86VidModeSetGamma'
!! Obtained 6 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x725482d633cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XF86VidModeSetGamma+0x27) [0x725482d63752]
!! xgamma(main+0x523) [0x6225716b5673]
!! /lib64/libc.so.6(+0x29386) [0x725482a22386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x725482a22447]
!! xgamma(_start+0x21) [0x6225716b5971]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'vidmode' and is using function 'XF86VidModeSetGammaRamp'
!! Obtained 7 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x79addf2c43cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(XF86VidModeSetGammaRamp+0x3a) [0x79addf2c4688]
!! redshift(+0x9ec1) [0x5bce6fc4fec1]
!! redshift(+0x3b84) [0x5bce6fc49b84]
!! /lib64/libc.so.6(+0x29386) [0x79addee4d386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x79addee4d447]
!! redshift(+0x4c81) [0x5bce6fc4ac81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! Obtained 7 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7d9287fd83cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(drmModeCrtcSetGamma+0x39) [0x7d9287fd85ac]
!! redshift(+0x8a69) [0x55d843f51a69]
!! redshift(+0x3b84) [0x55d843f4cb84]
!! /lib64/libc.so.6(+0x29386) [0x7d9287b61386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7d9287b61447]
!! redshift(+0x4c81) [0x55d843f4dc81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! Obtained 7 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7d9287fd83cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(drmModeCrtcSetGamma+0x39) [0x7d9287fd85ac]
!! redshift(+0x8a69) [0x55d843f51a69]
!! redshift(+0x3b84) [0x55d843f4cb84]
!! /lib64/libc.so.6(+0x29386) [0x7d9287b61386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7d9287b61447]
!! redshift(+0x4c81) [0x55d843f4dc81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'drm' and is using function 'drmModeCrtcSetGamma'
!! Obtained 7 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x7d9287fd83cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(drmModeCrtcSetGamma+0x39) [0x7d9287fd85ac]
!! redshift(+0x8a69) [0x55d843f51a69]
!! redshift(+0x3b84) [0x55d843f4cb84]
!! /lib64/libc.so.6(+0x29386) [0x7d9287b61386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x7d9287b61447]
!! redshift(+0x4c81) [0x55d843f4dc81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! Obtained 8 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x72f1835e13cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(xcb_randr_set_crtc_gamma_checked+0x3a) [0x72f1835e14cb]
!! redshift(+0x93a5) [0x5758f497d3a5]
!! redshift(+0x956a) [0x5758f497d56a]
!! redshift(+0x3b84) [0x5758f4977b84]
!! /lib64/libc.so.6(+0x29386) [0x72f18316a386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x72f18316a447]
!! redshift(+0x4c81) [0x5758f4978c81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! Obtained 8 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x72f1835e13cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(xcb_randr_set_crtc_gamma_checked+0x3a) [0x72f1835e14cb]
!! redshift(+0x93a5) [0x5758f497d3a5]
!! redshift(+0x956a) [0x5758f497d56a]
!! redshift(+0x3b84) [0x5758f4977b84]
!! /lib64/libc.so.6(+0x29386) [0x72f18316a386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x72f18316a447]
!! redshift(+0x4c81) [0x5758f4978c81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! Obtained 8 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x72f1835e13cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(xcb_randr_set_crtc_gamma_checked+0x3a) [0x72f1835e14cb]
!! redshift(+0x93a5) [0x5758f497d3a5]
!! redshift(+0x956a) [0x5758f497d56a]
!! redshift(+0x3b84) [0x5758f4977b84]
!! /lib64/libc.so.6(+0x29386) [0x72f18316a386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x72f18316a447]
!! redshift(+0x4c81) [0x5758f4978c81]
!! The program '/usr/bin/redshift' was called as: 'redshift' '-P' '-O' '3000' '-m' 'randr' and is using function 'xcb_randr_set_crtc_gamma_checked'
!! Obtained 8 stack frames.
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(__internalshie_print_trace+0x51) [0x72f1835e13cc]
!! /home/user/sandbox/c/hook/m1_2X/packed/libprog2.so(xcb_randr_set_crtc_gamma_checked+0x3a) [0x72f1835e14cb]
!! redshift(+0x93a5) [0x5758f497d3a5]
!! redshift(+0x956a) [0x5758f497d56a]
!! redshift(+0x3b84) [0x5758f4977b84]
!! /lib64/libc.so.6(+0x29386) [0x72f18316a386]
!! /lib64/libc.so.6(__libc_start_main+0x87) [0x72f18316a447]
!! redshift(+0x4c81) [0x5758f4978c81]

EDIT: I forgot to mention, you can't hook suid binaries (it's a security feature from glibc I believe), so in my case startx(&co) is not suid root, that's why it works:

$ ls -la `which startx` `which X` `which Xorg`
-rwxr-xr-x 1 root root    5142 27.05.2022 11:03 /usr/bin/startx*
lrwxrwxrwx 1 root root       4 14.07.2022 11:03 /usr/bin/X -> Xorg*
-rwxr-xr-x 1 root root 2467272 14.07.2022 11:03 /usr/bin/Xorg*           

I'm on Gentoo:

$ qfile `which Xorg` `which X` `which startx`
x11-apps/xinit: /usr/bin/startx
x11-base/xorg-server: /usr/bin/X
x11-base/xorg-server: /usr/bin/Xorg
x11-base/xorg-server-21.1.4::gentoo was built with the following:
USE="elogind udev unwind xorg xvfb -debug -minimal (-selinux) -suid -systemd -test -xcsecurity -xephyr -xnest" ABI_X86="(64)"