1.
Прежде всего, я хотел бы проверить себя, правильно ли я понимаю, что такое блоб в C в Linux:
All a binary blob is, is a pre-compiled shared object that is dynamically linked at runtime.
Это правильно? В общем, я должен получить файл .so
и через elf-loader загрузить файл в текущее пространство памяти и запустить функцию. Я использовал этот elf-loader и его образец hello.so
работает просто отлично.
2.
Теперь я должен создать .so
файл для запуска его через elf-loader. Как я уже отмечал здесь , мы не можем объединить файлы .so в один .so, но мы можем создать один файл .so
из нескольких библиотек stati c (.a
). И это то, что я выбрал (создание файла .so с использованием stati c libs).
3. Теперь я должен сказать, что у меня есть app-static.c
, который является исходным файлом, который использует stati c libs freetype
, libpng
и zlib
с именами libfreetype.a
libpng.a
libzlib.a
соответственно. Поэтому я хочу сделать app-static.c
архивом (stati c lib), а также объединить его с libfreetype.a
libpng.a
libzlib.a
, а затем создать общий файл .so
для загрузки через elf-loader.
4. Вот как я создаю объектный файл для выполнения слияния:
elvin@ubuntu:~/lab1KR/app$ gcc -c -fPIC app-static.c -I ../freetype/ -I ../libpng/ -I ../zlib/
Затем, когда объектный файл создан, я создаю c lib app-stati c. c
elvin@ubuntu:~/lab1KR/app$ ar -rsc libblob.a *.o
Затем я объединяю все 4 библиотеки:
elvin@ubuntu:~/lab1KR/app$ gcc -shared -fPIC -o c.so -Wl,--whole-archive libblob.a ../freetype/libfreetype.a ../libpng/libpng.a ../zlib/libzlib.a -Wl,--no-whole-archive
Когда это сделано, я получаю c.so
и хочу, чтобы он был загружен.
Для использования elf-loader требуется
wheelc folder, main.c folder, elf_loader.c and elf_loader.h
.
Я использую команду для создания elfloader.out:
elvin@ubuntu:~/lab1KR/app$ gcc -Wall -g -o elfloader elf_loader.c main.c wheelc/list.c -ldl
Это часть моего app-static.c
(который теперь является stati c lib), который я хочу выполнить как образец hello.so
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include<dirent.h>
#include <png.h>
...... .............
char* render_glyph(FT_Face* face, conf_t conf)
{
FT_Library ft;
FT_Error err;
err = FT_Init_FreeType(&ft);
if (err) return "freetype init error";
err = FT_New_Face(ft, conf.font_file, 0, face);
if (err == FT_Err_Unknown_File_Format)
return "unknown font file format";
else if (err)
return "error reading font file";
err = FT_Set_Pixel_Sizes(*face, 0, conf.size);
if (err) return "error setting font size";
int target_height;
target_height = HEIGHT;
FT_Vector pen;
FT_GlyphSlot slot;
slot = (*face)->glyph;
pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64;
int wid = 0;
for (int i = 0; i < strlen(conf.text); ++i)
{
FT_UInt index = FT_Get_Char_Index(*face, conf.text[i]);
//printf("FT_UInt index = %u\n", index);
if (index == 0) return "no glyph found for char";
err = FT_Load_Glyph(*face, index, FT_LOAD_DEFAULT);
if (err) return "error loading glyph";
err = FT_Render_Glyph((*face)->glyph, conf.anti_alias ?
FT_RENDER_MODE_NORMAL :
FT_RENDER_MODE_MONO);
if (err) return "error rendering glyph";
//draw_bitmap((*face)->glyph->bitmap);
//draw_bitmap( &slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top );
draw_bitmap( &slot->bitmap,
slot->bitmap_left + wid,
target_height - slot->bitmap_top-500);
wid += slot->bitmap.width;
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}
return NULL;
}
char* cool_render_png(char* out, int aa)
{
//char buf[500]="\0";
//strcat(buf,"../");
//strcat(buf,out);
FILE* f = fopen(out, "wb");
if (!f)
return "failed to open output file";
png_structp png_out = png_create_write_struct(
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_out)
return "failed to create png write struct";
png_infop png_info = png_create_info_struct(png_out);
if (!png_info)
return "failed to create png info struct";
//printf("init_begin\n");
//
if (setjmp(png_jmpbuf(png_out)))
return "png init io error";
png_init_io(png_out, f);
if (setjmp(png_jmpbuf(png_out)))
return "IHDR write error";
//printf("png_property\n");
//
png_set_IHDR(png_out,
png_info,
WIDTH,
HEIGHT,
aa ? 8 : 1,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_out, png_info);
//printf("another_png_property\n");
//
if (setjmp(png_jmpbuf(png_out)))
return "png write error";
int i;
for (i = 0; i < HEIGHT; ++i)
{
//printf("\ti - %i\n",i);
const unsigned char* rowptr = image[i];
png_write_row(png_out, rowptr);
}
//printf("write\n");
if (setjmp(png_jmpbuf(png_out)))
{
//printf("setjmp_error\n");
return "png end error";
}
//printf("setjmp\n");
png_write_end(png_out, NULL);
//printf("png_write_end\n");
fclose(f);
return NULL;
}
int main1()
{
clock_t begin =clock();
conf_t conf;
get_files_names();
memset(&conf, 0, sizeof(conf_t));
//conf->size = 72;
//conf->font_file="../*.ttf";
char buf[500]="\0";
int k=0;
for(k=0;k<files.rows;k++)
{
if(strstr(files.list_of_files[k],".ttf"))
{
//strcat(buf,"../");
strcat(buf,files.list_of_files[k]);
}
}
conf.font_file=(char*)calloc(strlen(buf)+1,sizeof(char));
memcpy(conf.font_file,buf,(strlen(buf)+1)*sizeof(char));
conf.name_png="default_name.png";
conf.text="default";
conf.size=72;
FT_Face face;
char* ft_err = render_glyph(&face, conf);
//printf("render_glyph\n");
if (ft_err != NULL)
{
printf("freetype error: %s\n", ft_err);
return 2;
}
//printf("bitmap rows: %d, width: %d\n",
// face->glyph->bitmap.rows,
// face->glyph->bitmap.width);
//char* png_err = render_png(face, "a.png", conf.anti_alias);
char* png_err = cool_render_png(conf.name_png, conf.anti_alias);
//printf("cool_render_png\n");
if (png_err != NULL)
{
printf("png error: %s\n", png_err);
return 3;
}
/*if(argc==1)
{
free(conf.font_file);
}*/
//printf("OK! File wa created!\n");
clock_t end=clock();
double time_spent=(double)(end-begin)/CLOCKS_PER_SEC;
printf("\n%f\n",time_spent);
return 0;
}
7. Теперь мне нужно запустить elfloader и c .so:
elvin@ubuntu:~/lab1KR/app$ ./elfloader ./c.so main1
И у меня возникла ошибка при разрешении символа:
[DEBUG elf_loader.c:403] RELO JMP_SLOT 0x7f7b256f3a00 <- 0x7f7b254a9ae4 png_write_hIST
[DEBUG elf_loader.c:352] Processing 'c.so' relocation at index 318
[DEBUG elf_loader.c:258] SEARCH gzwrite in c.so@0x7f7b253f0000 (gnu)
[DEBUG elf_loader.c:281] FOUND gzwrite in c.so (0xc5ef1) 584
[DEBUG elf_loader.c:324] elf module c.so sym gzwrite s->st_value = 0xc5ef1, found in c.so, base = 0x7f7b253f0000, load_bias = 0x7f7b253f0000
[DEBUG elf_loader.c:403] RELO JMP_SLOT 0x7f7b256f3a08 <- 0x7f7b254b5ef1 gzwrite
[DEBUG elf_loader.c:352] Processing 'c.so' relocation at index 319
[DEBUG elf_loader.c:258] SEARCH trunc in c.so@0x7f7b253f0000 (gnu)
[DEBUG elf_loader.c:262] NOT FOUND trunc in c.so@0x7f7b253f0000 (gnu)
[ERROR elf_loader.c:368] cannot locate symbol "trunc" referenced by "c.so"...
[DEBUG elf_loader.c:924] [ finished linking c.so, ret=0 ]
[DEBUG elf_loader.c:49] name c.so: freeing soinfo @ 0x55fad58ed670
[ERROR main.c:95] load_elf_module c.so failed
Он находит все функции, но не может найти trunc
. Я проверил, что это за trun c, используя usng grep, но не заметил, что trun c - это даже функция!
elvin@ubuntu:~/lab1KR$ grep -r -i "trunc"
Binary file app/c.so matches
zlib/deflate.c: * is longer, truncate the previous match to a single literal.
zlib/zlib.h: extra field, or that field truncated if extra_max is less than extra_len.
zlib/trees.c:#ifdef TRUNCATE_BLOCK
zlib/gzlib.c: O_TRUNC :
libpng/pngpread.c: /* This may be a truncated stream (missing or
libpng/pngpread.c: png_warning(png_ptr, "Truncated compressed data in IDAT");
libpng/pngwutil.c: "Truncating profile to actual length in iCCP chunk");
libpng/pngrutil.c: png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
libpng/pngrutil.c: png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
libpng/pngrutil.c: * sRGB and ITU Rec-709 both truncate the values for the D65 white
libpng/pngrutil.c: * digits, the PNG spec gives the truncated value.
libpng/pngrutil.c: png_warning(png_ptr, "Truncated zTXt chunk");
libpng/pngrutil.c: png_warning(png_ptr, "Truncated iTXt chunk");
libpng/pngrutil.c: png_warning(png_ptr, "Truncated iTXt chunk");
libpng/pngrutil.c: /* Get to here when the row_width truncates the final copy.
Binary file libpng/pngwutil.o matches
libpng/pngerror.c: * happen is that the message will be truncated appropriately.
Binary file libpng/pngpread.o matches
Binary file libpng/libpng.so matches
libpng/pngmem.c: * result, we would be truncating potentially larger memory requests
Binary file libpng/libpng.a matches
libpng/pngrtran.c: * truncates the results.
Binary file libpng/png.o matches
Binary file libpng/pngrutil.o matches
freetype/ftraster.c:#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
freetype/ftraster.c: e1 = (Int)TRUNC( miny );
freetype/ftraster.c: e1 = (Int)TRUNC( y1 );
freetype/ftraster.c: e2 = (Int)TRUNC( maxy );
freetype/ftraster.c: e2 = (Int)TRUNC( y2 );
freetype/ftraster.c: ras.cProfile->start = TRUNC( e0 );
freetype/ftraster.c: if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
freetype/ftraster.c: e1 = TRUNC( CEILING( x1 ) );
freetype/ftraster.c: e2 = TRUNC( FLOOR( x2 ) );
freetype/ftraster.c: e1 = TRUNC( e1 );
freetype/ftraster.c: e1 = TRUNC( e1 );
freetype/ftraster.c: e1 = TRUNC( e1 );
freetype/ftraster.c: e1 = TRUNC( e1 );
freetype/ftraster.c: e1 = TRUNC( e1 );
freetype/ftraster.c: e1 = TRUNC( e1 ) / 2;
freetype/ftraster.c: max_Y = (Short)TRUNC( ras.minY );
freetype/ftraster.c: min_Y = (Short)TRUNC( ras.maxY );
freetype/ftraster.c: ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
freetype/ftglyph.c: if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
freetype/ftgrays.c:#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
freetype/ftgrays.c: /* truncate the bounding box to integer pixels */
freetype/ftgrays.c: ex1 = TRUNC( x1 );
freetype/ftgrays.c: ex2 = TRUNC( x2 );
freetype/ftgrays.c: ey1 = TRUNC( ras.last_ey );
freetype/ftgrays.c: ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
freetype/ftgrays.c: TCoord ex = TRUNC( ras.x );
freetype/ftgrays.c: gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
freetype/ftgrays.c: gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
freetype/ftgrays.c: if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
freetype/ftgrays.c: if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
freetype/ftgrays.c: gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
freetype/freetype/freetype.h: /* The glyph name is truncated to fit within the buffer if it is too */
freetype/freetype/internal/ftmemory.h: /* Return >= 1 if a truncation occurs. */
freetype/freetype/ftglyph.h: /* FT_GLYPH_BBOX_TRUNCATE :: */
freetype/freetype/ftglyph.h: FT_GLYPH_BBOX_TRUNCATE = 2,
freetype/freetype/ftglyph.h: /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */
freetype/freetype/ftglyph.h:#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE
freetype/freetype/ftglyph.h: /* @FT_GLYPH_BBOX_TRUNCATE. */
elvin@ubuntu:~/lab1KR$
Это просто препроцессор, а препроцессор не является функцией в все! Где я был не прав в создании блоба? Это правильный способ создать его? Если это то, почему я получаю ошибку? Как решить эту проблему? Не могли бы вы помочь мне? Заранее спасибо!