Redefining fputc function when using arm-none-eabi toolchain - c

We have an STM32 C/C++ project and we have redefined the weak fputc(int, FILE *) function in order to redirect printf output to some UART channel.
Up until now, we were building the project under IAR with the IAR compiler. The logging through UART was working fine.
We have now switched to the arm-none-eabi toolchain and are building the project with g++. But it looks like the redefinition of the fputc function is not linked anymore and so the UART logging is not working.
How can I force the use of the redefined function by printf?

The arm-none-eabi- toolchain is using newlib, which lets you redefine _write(int fd, const void *buf, size_t count) instead, all stdio output functions would then use that interface. fd==1 would correspond to stdout, fd==2 to stderr. You must provide a few more stub functions, like
void _exit(int) {
while(1)
;
}
etc. Most of them are trivial, but printf() requires a working _sbrk() too, because it uses malloc() internally.

Just had the same problem converting project from Keil to Cube. Found this elegant STM32 printf retarget to UART solution on GitHub (and please forgive the copy-paste):
/*# 7- Retarget printf to UART (std library and toolchain dependent) #########*/
#if defined(__GNUC__)
int _write(int fd, char * ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
return len;
}
#elif defined (__ICCARM__)
#include "LowLevelIOInterface.h"
size_t __write(int handle, const unsigned char * buffer, size_t size)
{
HAL_UART_Transmit(&huart1, (uint8_t *) buffer, size, HAL_MAX_DELAY);
return size;
}
#elif defined (__CC_ARM)
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
#endif
// OR:
// Add syscalls.c with GCC
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
* #brief Retargets the C library printf function to the USART.
* #param None
* #retval None
*/
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
This may or may not work in your particular case, but you get the Idea...
In my case, I had to prepend function type with extern "C" :
extern "C" int _write(int fd, char * ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
return len;
}

Related

Uneven behavior in different system calls hooking

I am working on a project in which i have hooked the system open call. When a user attempts to open a file i want sys_open to block the action if the current task (pid or tgid that "black listed" ) has potential to leak the file out of the host.
Any ways, the hooking itself worked fine on sys_read and sys_write (I have some printk inside the fake function as an indicator).
but, when i try the hooking on the sys_open function, nothing is printed out - means that the override not succeeded.
I printed out the address of the sys call before and after the override so this might not be the issue.
I am confused about what can cause that uneven behavior when hooking different functions.
will be glad for some input here.
thanks !
dmesg output examples:
when hooked write -
...
[ 2989.500485] in my write ...
[ 2989.500585] in my write ...
when hooked open, noting printed, but here some "debug" output -
[ 890.709696] address found 00000000103d42f6
[ 890.709697] Address before - 0000000006d29c3a
[ 890.709698] Address after - 00000000a5117c6a
[ 948.533339] BYE !!!
using lubuntu vm (kernel v 4.15.0.20).
here is the source code:
#include <linux/init.h> // Macros used to mark up functions e.g., __init __exit
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/syscalls.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/page.h>
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/set_memory.h>
#include <linux/cred.h>
#include <linux/user.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ABC");
MODULE_VERSION("0.1");
asmlinkage long (*original_call)( char __user *filename, int flags, umode_t mode); // for read or write: (unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode);
unsigned long* find_sys_call_table(void);
void set_page_rw( unsigned long addr);
void set_page_ro( unsigned long addr);
const struct cred *_cred = NULL ;
struct user_struct *user =NULL ;
unsigned long* sys_call_table = NULL;
void set_page_rw(unsigned long addr)
{
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
}
void set_page_ro( unsigned long addr)
{
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
pte->pte = pte->pte &~_PAGE_RW;
}
/*
asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count)
{
//_cred = current_cred();
user = get_current_user();
if( (int)(*user).uid.val == uid )
{
printk(KERN_ALERT"in my read ... hacked !");
return original_call(fd, buf, count);
}
printk(KERN_ALERT"in my read ... hacked !");
return original_call(fd, buf, count);
}
asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count)
{
//_cred = current_cred();
user = get_current_user();
if( (int)(*user).uid.val == uid )
{
printk(KERN_ALERT"in my write ... hacked !");
return original_call(fd, buf, count);
}
printk(KERN_ALERT"in my write ... hacked !");
return original_call(fd, buf, count);
}
*/
asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode)
{
printk(KERN_ALERT"in my open ... hacked !");
return original_call(filename, flags, mode);
}
unsigned long* find_sys_call_table(void)
{
return (unsigned long *)kallsyms_lookup_name("sys_call_table");
}
int init_module()
{
printk(KERN_ALERT "I'm dangerous. I hope you did a ");
printk(KERN_ALERT "sync before you insmod'ed me.\n");
sys_call_table = find_sys_call_table();
printk(KERN_INFO"address found %p \n",sys_call_table);
original_call = (void *)sys_call_table[__NR_open];
set_page_rw((unsigned long)sys_call_table);
printk(KERN_INFO" Address before - %p", (void *)sys_call_table[__NR_open]);
sys_call_table[__NR_open] = (unsigned long)my_sys_OPEN;
printk(KERN_INFO" Address after - %p", (void *)sys_call_table[__NR_open]);
return 0;
}
/*
* Cleanup − unregister the appropriate file from /proc
*/
void cleanup_module()
{
/*
* Return the system call back to normal
*/
if (sys_call_table[__NR_open] != (unsigned long)my_sys_OPEN) {
printk(KERN_ALERT "Somebody else also played with the ");
printk(KERN_ALERT "open system call\n");
}
printk(KERN_ALERT "BYE !!!\n");
sys_call_table[__NR_open] = (unsigned long)original_call;
}
Your Ubuntu version is based on glibc 2.27.
glibc version 2.26 switched to implementing open with openat:
commit b41152d716ee9c5ba34495a54e64ea2b732139b5
Author: Adhemerval Zanella <adhemerval.zanella#linaro.org>
Date: Fri Nov 11 15:00:03 2016 -0200
Consolidate Linux open implementation
This patch consolidates the open Linux syscall implementation on
sysdeps/unix/sysv/linux/open{64}.c. The changes are:
1. Remove open{64} from auto-generation syscalls.list.
2. Add a new open{64}.c implementation. For architectures that
define __OFF_T_MATCHES_OFF64_T the default open64 will create
alias to required open symbols.
3. Use __NR_openat as default syscall for open{64}.
You will have to hook openat in addition to open as a result.
Note that the Linux kernel provides a proper interface for this, in the form of the fanotify interface. If you use that, you will not have to worry about such details.

How to print to console (Linux) without the standard library (libc)

I'm not using the standard library, since my target x86 Linux distro is very limited.
#include <unistd.h>
void _start () {
const char msg[] = "Hello world";
write( STDOUT_FILENO, msg, sizeof( msg ) - 1 );
}
I want to print text to console, but I can't, is there any other way to do this.
The code above wont work because it depends on standard library
gcc Test.cpp -o Test -nostdlib
If you don't have libc, then you need to craft a write() system call from scratch to write to the standard output.
See this resource for the details: http://weeb.ddns.net/0/programming/c_without_standard_library_linux.txt
Code example from the above link:
void* syscall5(
void* number,
void* arg1,
void* arg2,
void* arg3,
void* arg4,
void* arg5
);
typedef unsigned long int uintptr; /* size_t */
typedef long int intptr; /* ssize_t */
static
intptr write(int fd, void const* data, uintptr nbytes)
{
return (intptr)
syscall5(
(void*)1, /* SYS_write */
(void*)(intptr)fd,
(void*)data,
(void*)nbytes,
0, /* ignored */
0 /* ignored */
);
}
int main(int argc, char* argv[])
{
write(1, "hello\n", 6);
return 0;
}

How to retarget printf() on an STM32F10x?

I use this code for retarget printf(), but it does not work
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the LCD */
lcd_Data_Write((u8)ch);
return ch;
}
I use STM32F103RBT6
compiler : GCC with emBitz editor
Try hijacking the _write function like so:
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, char *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO: /*stdout*/
// Send the string somewhere
break;
case STDERR_FILENO: /* stderr */
// Send the string somewhere
break;
default:
return -1;
}
return len;
}
As an alternative, you could write your own printf() function using, Variable Argument Functions (va_list).
With va_list a custom print function looks like the following:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void vprint(const char *fmt, va_list argp)
{
char string[200];
if(0 < vsprintf(string,fmt,argp)) // build string
{
HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
}
}
void my_printf(const char *fmt, ...) // custom printf() function
{
va_list argp;
va_start(argp, fmt);
vprint(target, fmt, argp);
va_end(argp);
}
Usage example:
uint16_t year = 2016;
uint8_t month = 10;
uint8_t day = 02;
char* date = "date";
// "Today's date: 2015-12-18"
my_printf("Today's %s: %d-%d-%d\r\n", date, year, month, day);
Note that while this solution gives you convenient function to use, it is slower than sending raw data or using even sprintf(). I have used this solution both on AVR and on STM32 microcontrollers.
You could further modify the vprint like this, where periphery_t is a simple enum type:
void vprint(periphery_t target, const char *fmt, va_list argp)
{
char string[200];
if(0 < vsprintf(string,fmt,argp))
{
switch(target)
{
case PC: PC_send_str(string);
break;
case GSM: GSM_send_str(string);
break;
case LCD: LCD_print_str(string);
break;
default: LCD_print_str(string);
break;
}
}
}
Tank you Bence Kaulics
I use tinyprintf library and it worked quite well : github link
just make sure to add the following in the init code:
// Turn off buffers, so I/O occurs immediately
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);

gcc Warning Passing argument 2 of 'alt_16550_fifo_write' makes pointer from integer without a cast

I am currently working on a project involving a Cyclone V ARM Cortex A9 Processor and an external device. I am relatively new in C Programming. I am using the UART interface of the processor to send and receive data from the external with help of APIs in C. When i compile my code, I get warnings that I am passing arguments that make pointer from integer without a cast in the function alt_16550_fifo_write(). Can someone please help?
Below is my code
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <stdbool.h>
#include <sys/types.h>
#include "ergo.h"
#include "alt_clock_manager.h"
#include "hwlib.h"
#include "alt_clock_group.h"
#include "alt_hwlibs_ver.h"
#include "alt_16550_uart.h"
#include "uart.h"
#include "socal/alt_clkmgr.h"
#include "socal/alt_rstmgr.h"
#include "socal/alt_uart.h"
#include "socal/hps.h"
#include "socal/socal.h"
/* commands to control the ergo bike */
#define ERGO_CMD_GET_ADDRESS 0x11
#define ERGO_CMD_RUN_DATA 0x40
#define ERGO_CMD_SET_WATT 0x51
#define UART_MAX_DATA 20
#define enable_init TRUE
/*Global Variables*/
ergo_run_data_t ergo_run_data;
u_int8_t ergo_adr_int;
/* External Functions that are called in the main function*/
static ALT_STATUS_CODE alt_16550_reset_helper(ALT_16550_HANDLE_t * handle, bool enable_init);
static inline uint32_t alt_read_word_helper(const void * addr);
static ALT_STATUS_CODE alt_16550_write_divisor_helper(ALT_16550_HANDLE_t * handle,uint32_t divisor);
ALT_STATUS_CODE alt_clk_clock_enable(ALT_CLK_t ALT_CLK_L4_SP);
ALT_STATUS_CODE alt_clk_is_enabled(ALT_CLK_t ALT_CLK_L4_SP);
ALT_STATUS_CODE alt_clk_freq_get(ALT_CLK_t ALT_CLK_L4_SP,alt_freq_t* freq);
ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle,const char * buffer,size_t count);
void ergo_get_address(ALT_16550_HANDLE_t * handle);
void ergo_get_run_data(void);
void ergo_set_watt(u_int8_t ergo_adr_int, u_int8_t watt);
void ergo_reset(ALT_16550_HANDLE_t * handle,u_int8_t ergo_adr_int);
void ergo_break(void);
/*function to enable the SOCFPGA UART Clock*/
ALT_STATUS_CODE alt_clk_clock_enable(ALT_CLK_t ALT_CLK_L4_SP)
{
if (alt_clk_clock_enable(ALT_CLK_L4_SP) != ALT_E_ERROR)
{
return ALT_E_SUCCESS; // The operation was successfull
}
else
{
return ALT_E_ERROR; // The operation was not successfull
}
}
/*Function to check whether the SOCFPGA Clock is enabled*/
ALT_STATUS_CODE alt_clk_is_enabled(ALT_CLK_t ALT_CLK_L4_SP)
{
ALT_16550_HANDLE_t * handle;
handle->clock_freq = 0;
if (alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE)
{
return ALT_E_BAD_CLK;
}
else
{
ALT_STATUS_CODE status;
status = alt_clk_freq_get(ALT_CLK_L4_SP, &handle->clock_freq);
}
}
//function to get the clock frequency
ALT_STATUS_CODE alt_clk_freq_get(ALT_CLK_t ALT_CLK_L4_SP,alt_freq_t* freq)
{
ALT_16550_HANDLE_t * handle;
handle->clock_freq = 0;
ALT_STATUS_CODE status;
status = alt_clk_freq_get(ALT_CLK_L4_SP, &handle->clock_freq);
if (status != ALT_E_SUCCESS)
{
return status;
}
}
struct uart_data_t
{
size_t tx_count; /*amount of data to send*/
char tx_buffer[UART_MAX_DATA]; /*data to send*/
size_t rx_count; /*amount of data to send*/
char rx_buffer[UART_MAX_DATA]; /*data received*/
}uart_data_t;
/*==========================UART functions======================*/
/*----------------------------- uart_init() -------------------------*/
/**
* Übergabeparameter: -
* Return: -
* Funktion: Initialisiert UART-Schnittstelle
*---------------------------------------------------------------------*/
int main()
{
/* Open File Descriptor */
int USB = open( "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK);
//Error Handling
if ( USB < 0 )
{
printf("Error beim oeffnen");
}
// Configure Port
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
// Error Handling
if ( tcgetattr ( USB, &tty ) != 0 )
{
printf("error beim tcgetattr");
}
// Save old tty parameters
tty_old = tty;
ALT_16550_HANDLE_t * handle;
handle->data;
handle->fcr;
handle->clock_freq;
handle->location; //ALT_UART0_ADDR
handle->device;
//ALT_16550_DEVICE_SOCFPGA_UART0 = 0; //This option selects UART0 in the SoC FPGA
ALT_16550_DEVICE_t device;
ALT_STATUS_CODE status;
alt_freq_t clock_freq;
void *location;
const void * addr;
bool enable_init;
uint32_t baudrate = ALT_16550_BAUDRATE_9600;
uint32_t divisor; //((handle->clock_freq + (8 * baudrate)) / (16 * baudrate));
printf("Program start \n");
// Enable the UART Clock
alt_clk_clock_enable(ALT_CLK_L4_SP);
// Helper function to reset and Initialise the UART (UART 0)
alt_16550_reset_helper(handle, enable_init);
// Helper function to carryout the actual register read.
alt_read_word_helper(addr);
//Helper function to write the divisor in Hardware
alt_16550_write_divisor_helper(handle,divisor);
//Enable the UART (UART 0)
alt_16550_enable(handle);
//Enable the FIFO
alt_16550_fifo_enable(handle);
//Get the Ergometer address
ergo_get_address(handle);
return 0;
}
/*--------------------------- ergo_get_adr() ------------------------*/
/**
* Übergabeparameter: -
* Return: -
* Funktion: Holen der Ergometer-Adreesse (1 Byte)
*---------------------------------------------------------------------*/
void ergo_get_address(ALT_16550_HANDLE_t * handle)
{
struct uart_data_t data;
/* build up data frame for address request */
data.tx_count = 1; // amount of data to send
data.tx_buffer[0] = ERGO_CMD_GET_ADDRESS;
data.rx_count = 2; /*amount of data to receive*/
/* get address from ergo bike */
alt_16550_fifo_write(handle, *ERGO_CMD_GET_ADDRESS,1);
alt_16550_fifo_read(handle,data.rx_buffer,2);
/* save ergo address if the bike responded */
if(data.rx_buffer[0] == ERGO_CMD_GET_ADDRESS)
{
ergo_adr_int = data.rx_buffer[1];
printf("%d\n",data.rx_buffer[1]);
}
/* wait for 50ms */
ergo_break();
return;
}
/*---------------------------- ergo_reset() -------------------------*/
/**
* Übergabeparameter: u_int8_t ergo_adr_int
* Return: -
* Funktion: Setzt Ergometer zurück
*---------------------------------------------------------------------*/
void ergo_reset(ALT_16550_HANDLE_t * handle,u_int8_t ergo_adr_int)
{
alt_16550_fifo_write(handle,0x12,1);
alt_16550_fifo_write(handle,ergo_adr_int,1);
ergo_break();
return;
}
/*---------------------------- ergo_break() -------------------------*/
/**
* Übergabeparameter: -
* Return: -
* Funktion: Wait for about 50 ms
*---------------------------------------------------------------------*/
void ergo_break(void)
{
u_int16_t d1;
u_int8_t d2;
//wait for ~50 ms
for(d1=0; d1 < 65535; d1++)
{
for(d2=0; d2 < 64; d2++)
{
}
}
return;
}
In your code, your function prototype is
ALT_STATUS_CODE alt_16550_fifo_write
(ALT_16550_HANDLE_t * handle,const char * buffer,size_t count);
the second parameter being const char * buffer.
While calling this function, you're using
void ergo_reset(ALT_16550_HANDLE_t * handle,u_int8_t ergo_adr_int)
{
alt_16550_fifo_write(handle,0x12,1);
alt_16550_fifo_write(handle,ergo_adr_int,1);
ergo_break();
return;
}
here, 0x12 and ergo_adr_int are not of type const char *.
0x12 is an integer constant (hexadecimal constant, to be precise) #.
ergo_adr_int is of u_int8_t type.
Hence the mismatch and the warning(s).
To Resolve
You need to pass a const char * variable as the second argument of the fuunction.
# :: As per C11 standard document, chapter 6.4.4.1, Integer constants,
hexadecimal-constant:
hexadecimal-prefix hexadecimal-digit
hexadecimal-constant hexadecimal-digit
Where
hexadecimal-prefix: one of
0x 0X
and
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
Here is the declaration of you alt_16550_fifo_write function
ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle,const char * buffer,size_t count);
The second parameter is of a pointer type but in your program you are always passing integer values:
alt_16550_fifo_write(handle,0x12,1);
alt_16550_fifo_write(handle,ergo_adr_int,1);
You need to pass a pointer to a char. For example:
alt_16550_fifo_write(handle, &(char) {0x12}, 1);
or
char x = 0x12;
alt_16550_fifo_write(handle, &x, 1);
Prototype for alt_16550_fifo_write() is:
ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle,
const char * buffer, size_t count);
You are using it at two places:
alt_16550_fifo_write(handle, *ERGO_CMD_GET_ADDRESS,1);
...
alt_16550_fifo_write(handle,0x12,1);
The second parameter is wrong. It should be const char * buffer, for example some string.

Compiling pyd file on windows but "This program cannot be run in DOS mode."

I was compiling a C file with gcc on Windows and got pyd file successfully. To my surprise, it shows "This program cannot be run in DOS mode" in hex. Although I still can call the function from it, the program crashed soon, caused by jpeg_read_header() from libjpeg library.
My question is what on earth made my program crashed.
Here are my guesses:
jpeg_read_header() : I tried both jpeg_mem_src() and jpeg_stdio_src() but it still crashed.
int _read_dct_coefficients(FILE* input_file, int** all_dcts)
{
JDIMENSION i, compnum, rownum, blocknum;
JBLOCKARRAY row_ptrs[MAX_COMPONENTS];
size_t block_row_size;
int num_blocks = 0, cnt = 0;
#ifdef LOG_DEBUG
log_debug(__LINE__, "enter _read_dct_coefficients");
#endif
/* init decompression */
srcinfo.err = jpeg_std_error(&jsrcerr);
jpeg_create_decompress(&srcinfo);
/* init compression */
dstinfo.err = jpeg_std_error(&jdsterr);
jpeg_create_compress(&dstinfo);
jsrcerr.trace_level = jdsterr.trace_level;
srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
#ifdef LOG_DEBUG
log_debug(__LINE__, "%%%%%%%MY TEST # 1%%%%%%%%");
#endif
//***************************************************************
unsigned int get_file_size(FILE *fp)
{
unsigned long filesize = -1;
if(fp == NULL)
return filesize;
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
fclose(fp);
return filesize;
}
int size = get_file_size(input_file);
#ifdef LOG_DEBUG
log_debug(__LINE__, "file size = %d", size);
#endif
char *tmp_buf = (unsigned char *)malloc(sizeof(char) * size);
if (size != fread(tmp_buf, 1, size, input_file))
log_debug(__LINE__, "cannot open.");
jpeg_mem_src(&srcinfo, tmp_buf, size);
/*
jpeg_stdio_src(&srcinfo, input_file);
*/
#ifdef LOG_DEBUG
log_debug(__LINE__, "%%%%%%%MY TEST # 2%%%%%%%%");
#endif
jpeg_read_header(&srcinfo, TRUE);
......
}
Pyd file : It cannot be run in DOS mode?
A Python .pyd file is just a DLL, which is just a Windows PE file. Windows PE files by convention start with a stub that prints that message if you run them in DOS:
https://en.wikipedia.org/wiki/Portable_Executable#History
Pretty much every Windows EXE and DLL file contains this header; it doesn't imply anything special.

Resources