LINUX.ORG.RU

Сообщения pavlick

 

Нарисавать пунктирную линию

Привет. Раньше всё было просто - для линии задавалась битовая маска.

     glLineStipple(1, 0x00ff);
     glEnable(GL_LINE_STIPPLE);
     glBegin(GL_LINE);
     ...
     glEnd();
Как это сделать в новом стиле? В сети пишут про использование текстуры, но ни одного примера. Ребята помогите, если не сложно. Я набросал заготовку, рисует диагональ.
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <utility>
#include <chrono>
#include <thread>
#include <iostream>

static const char *vertexShaderSource =
   "#version 330 core\n"
   "layout (location = 0) in vec2 position;\n"
   "void main() {\n"
   "   gl_Position = vec4(position.x, position.y, 0, 1.0);\n"
   "}\n";
static const char *fragmentShaderSource =
   "#version 330 core\n"
   "out vec4 color;\n"
   "void main() {\n"
   "   color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
   "}\n";

class Shader_prg
{
   GLuint shaderProgram;
public:
   Shader_prg(const char *vs, const char *fs)
   {
      GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
      glShaderSource(vertexShader, 1, &vs, NULL);
      glCompileShader(vertexShader);

      GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
      glShaderSource(fragmentShader, 1, &fs, NULL);
      glCompileShader(fragmentShader);

      this->shaderProgram = glCreateProgram();
      glAttachShader(this->shaderProgram, vertexShader);
      glAttachShader(this->shaderProgram, fragmentShader);
      glLinkProgram(this->shaderProgram);

      glDeleteShader(vertexShader);
      glDeleteShader(fragmentShader);
   }
   ~Shader_prg() {glDeleteProgram(this->shaderProgram);}
   Shader_prg(Shader_prg &) = delete;
   Shader_prg &operator=(Shader_prg &) = delete;
   operator GLuint() {return this->shaderProgram;}
   void use() { glUseProgram(this->shaderProgram); }
};

int main(void)
{
   using namespace std::chrono_literals;
    if (!glfwInit())
        return -1;
    GLFWwindow* window = glfwCreateWindow(800, 600, "Hello World", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK)
       return -1;
    Shader_prg sh_prg{vertexShaderSource, fragmentShaderSource};

    GLfloat vertices[] = {-1.0, -1.0,    1.0,  1.0};
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glEnableVertexAttribArray(0);
    glBindVertexArray(0);

    // Создаю текстуру
    GLuint txtr;
    glGenTextures(1, &txtr);
    glBindTexture(GL_TEXTURE_1D, txtr);
//    glTexImage1D(GL_TEXTURE_1D, ...)

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        glClearColor(0.1f, 0.25f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        sh_prg.use();
        glBindVertexArray(vao);
        glDrawArrays(GL_LINES, 0, 2);

        glfwSwapBuffers(window);
        std::this_thread::sleep_for(30ms);
    }

    glfwTerminate();
    return 0;
}
И хотелось бы генерить текстуру во время выполнения, а не тоскать с собой рисунок. Может можно что-то хитрое во фрагментном шейдере и текстура не нужна? Я тут не очень силён, прошу помочь.

 

pavlick ()

Structured binding

Приветствую. Чувствую себя идиотом :), несколько часов читаю справочник https://en.cppreference.com/w/cpp/language/structured_binding и не могу въехать.

A structured binding declaration first introduces a uniquely-named variable (here denoted by e) to hold the value of the initializer, as follows:
*If expression has array type A and no ref-operator is present, then e has type cv A, where cv is the cv-qualifiers in the cv-auto sequence, and each element of e is copy- (for (1)) or direct- (for (2,3)) initialized from the corresponding element of expression.
*Otherwise e is defined as if by using its name instead of [ identifier-list ] in the declaration.

Сначала вводится переменная e, а что означает подчёркнутое ну вот никак не пойму, по-моему, бред какой-то.
Едем дальше - связывание с tuple-like типом:

For each identifier, a variable whose type is «reference to std::tuple_element<i, E>::type» is introduced: lvalue reference if its corresponding initializer is an lvalue, rvalue reference otherwise.

Т.е. для каждого идентификатора создаётся ссылка (lvalue или rvalue), давайте проверим

   std::tuple<int> t{};
   auto [a] = t;
   cout << is_reference<decltype(a)>() << endl; // cout: 0
Скажите, дело во мне, а все нормальные это понимают?

 

pavlick ()

Использование new перед main()

Привет.
Я вот давно думаю - а можно ли использовать new expression перед main (например, в конструкторе глобального объекта). Я прошвырнулся по стандарту и справочнику - ответа не нашёл. В сети народ инициализируют глобальные вектора недефолтными конструкторами но хз. Ну мало ли - будет над new какая-нибудь надстройка в виде глобального менеджера памяти, которой будет инициализирован после моего цпп модуля, всё - попал в просак.

int *pi = new int;
int main() {return 0;}

 

pavlick ()

cups, печать из консоли, шрифт

Привет. Уточню сразу - меня сейчас всё устраивает, шрифт моноширинный, размер подходящий, но для общего развития интересно. Каким шрифтом печатается текст при вводе

$ lp file
В сети говорят, что размер можно настроить через -o cpi -o lpi (работает, но маны молчат по этому поводу почему-то). А шрифт как поменять? Понимаю, что можно взять какую-нибудь text_to_postscript | lp, но интересна голая lp. Я не призываю кого-то активно гуглить, может кто знает и поделится информацией. Проштудировал /etc/cups/cupsd.conf, ни слова там про шрифт.

 

pavlick ()

Выбираем принтер

Ребята, посоветуйте из лчного опыта - какой принтер прикупить (чем дешевле,тем лучше)? Так чтобы не плясать с бубном вокрук него. Монохромный, лазерный. Я так понимаю, что нафиг всякую заливку прошивки, чтоб с дровами не вышла беда. В общем, хочется печатать без боли.

 

pavlick ()

Завести принтер HP LaserJet 1018

Всем привет.
В общем всё по уродски с этой штуковиной, через костыли (нужно залить в принтер прошивку, и, конечно же, надо было придумать особенный протокол ZjStream). Вообще я немного в шоке - сколько зависимостей тянет за собой желание попечатать (не одна сотня мб, второй веб-браузер).

hplip пробовал - но она не находит прошивку для принтера (можно было попробовать подсунуть, но идёт она лесом).

Поставли cups, foomatic, foo2zgs. Залил прошивку через udev правило:

KERNEL=="lp*", ATTRS{manufacturer}=="Hewlett-Packard", ATTRS{product}=="HP LaserJet 1018", ATTRS{serial}=="KP0GJB5", RUN+="/bin/sh -c 'cat /usr/share/foo2zjs/firmware/sihp1018.dl > %N'"
Т.е. при включении принтера выполняется 'cat /usr/share/foo2zjs/firmware/sihp1018.dl > /dev/usb/lp0'. Настроил cups:
# lpadmin -p hp1018 -v "usb:/dev/usb/lpo" -E \
   -P /usr/share/cups/model/HP-LaserJet_1018.ppd.gz
# lpadmin -d "hp1018"
На первый взгляд всё нормально, но при попытке что-нибудь напечатать принтер пошумит немного, погреет печку и умерает. Дальше в него даже прошивка не встаёт (при заливки прошивки на нём мигает светодиод). Вернуть способность принимать прошивку удалось лишь подключением к винде (заливка прошивки родными утилитами). Может кто еба сталкивался с этим чудом? Как его оживить? Может я как-то неправильно заливаю прошивку?

 ,

pavlick ()

xpbs, void linux, конфликты во время установки

Привет. Про конфликты в xbps манах вообще ничего, по-моему. Столкнулся сейчас с двумя:
1

root-7 /usr/local/lrepo # xbps-install glu-devel
libglapi-18.2.4_1 (update) breaks installed pkg `mesa-nouveau-dri-18.2.3_1'
2
root-7 /usr/local/lrepo # xbps-install libxml2-devel
libharfbuzz-2.0.2_1: broken, unresolvable shlib `libicudata.so.62'
firefox-62.0.3_1: broken, unresolvable shlib `libicui18n.so.62'
firefox-62.0.3_1: broken, unresolvable shlib `libicuuc.so.62'
libharfbuzz-2.0.2_1: broken, unresolvable shlib `libicuuc.so.62'
При создании пакета через xbps-create можно задавать конфликтующие пакеты, может это они? Но как посмотреть несовместимые пакеты у libglapi или mesa-nouveau-dri, например, я так и не понял (xbps-query -Sv ... ничего не говорит). В общем, если сталкивались, то любая инфа по теме полезна (как интерпретировать сообщения? В каком пакете прописаны пакеты-конфликты? как посмотреть список конфликтов?). Я, вообще, собираю wine, в репозитории не оказалось его, решил создать виртуальный пакет с зависимостями и скомпилировать из исходников.

 

pavlick ()

Байндинг на ctrl + ...

Здравствуйте. Проблема в следующем - забайндил на всякие C-; C-, C-. нужные мне команды (rtags, iedit ...), раньше всё это работало (запускал gui emacs). Сейчас собрал emacs отключив всё что можно, запускаю его в консоли. Появилась проблема - нажатие C-; и смежных воспринимается им как нажатие без ctrl.

C-h k
C-;
; runs the command ...
Просьба: кому не сложно, проверьте, какой у вас будет выхлоп после запуска редактора $ emacs -nw с последующим C-h k и С-; . Нужно понять - это ограничение консольного emacs, я криво собрал редактор или ещё чего-то где-то отломал.
ЗЫ: консоль иксовая.

 

pavlick ()

Сменить сочетание Alt+Ctrl+F.. под X

1. Привет. Хочу иметь общий стиль переключения между VT терминалами и X (winkey+F..), назначил Alt на winkey в VT, а как на Х сменить комбинацию? В голову приходит xbindkey, но можно ли что-то подстроить в раскладке иксов (ну ведь это как-то дешевле, чем запущенный демон)? Не хочется перерыть кучу инфы и узнать, что ничего не получится, нужен xbindkey.

2. Кто-нибудь знает какую-нибудь утилиту, которая перебрасывает текст между X primary буфером и gpm буфером. Я знаю про xsel/xclip, но хочется большего комфорта - выделил мышью в иксах и это оказалось в gpm (без дополнительных телодвижений). Думал свою написать - в каком-то демоне запущен xsel и при появлении текста он дергает libgpm, но может готовое что-то есть. Или может можно как-то вставить текст в gpm буфер консольной командой (без мыши, типа этого: gpm-tool «paste this in buffer»)?

 

pavlick ()

Своё ядро в не source based дистрах

Привет. Только что поставил арч, и кое-чего не понял:
Во время установки в /boot лежало моё старое ядро ручной сборки, установщик решил, что ядро актуально и ничего не добавил (кроме initramfs). Я не против собирать своё ядро со своим конфигом (ну удобно ведь - дрова добавить и т.д), но возникает вопрос: софт в репозитории скомпилирован для конкретного ядра (glibc, например), какую версию ядра собирать? Брать тот же мажорный номер (ну это логично, но как это принято в приличных местах, какие официальные рекомендации)? Или сборка ядра приветствуется только в source-based (gentoo).
Не, ну в целом я догадываюсь как делать - тупо собирать последнее ядро перед перед каждым обновлением системы. Интересно - как вы делаете?

 

pavlick ()

Виртуальная консоль (не иксовая)

Привет. Проблема вот в чём: отечественные kbd раскладки в /usr/share/kbd/keymaps/ru* имеют одну неприятную особенность - правый alt != левому alt (если текущая раскладка латиница, то правый alt+.. даёт кириллицу). Пробовал много, но оник все кривые. Так как пользуюсь emacs'ом, это неудобно. Навскидку попытался затереть все altgr строки в файле-раскладке, но успехом это не увенчалось. Как можно сделать два alt равноправными (любой alt+b в emacs - на слово назад, например)? Искать другую раскладку, править текущую, есть хитрая команда для переназначения?

 

pavlick ()

Снести .la архивы у установленного софта

Здравствуйте. Ставлю LFS/BLFS и столкнулся с одной трудностью - не могу никак въехать в суть проблемы. http://www.linuxfromscratch.org/blfs/view/stable/introduction/la-files.html. Если коротко, то предлагается снести почти все libtool архивы (.la) и подправить все файлы от pkg-config так, чтобы они ссылались на обычные либы. Аргументация примерно такая (как я понял) - мол какая-то либа может обновиться и не использоввать больше libtool, и последующая линковка с такой либой вызовет ошибку. Я нахожу это ерундой какой-то, ну если она обновится, то обновит и .pc файл от pkg-config и не будет больше линковаться с .la libtool архивом. Я чего-то не допонял? Действительно разумно сносить .la архивы от устанавливаемого софта? Хочу понимать что делаю, а не просто копипастить. Слова автора

The problem is that libtool usually creates one or more text files for package libraries called libtool archives. These small files have a ".la" extention and contain information that is similar to that embedded in the libraries. When building a package that uses libtool, the process automatically looks for these files. If a package is updated and no longer uses the .la file, then the build process can break.

 ,

pavlick ()

Кириллица в консоли

Привет. Хочу её в не в x консоли, а в vt. Кодировка utf-8. Вроде бы логично всё делаю:

root@pc:/home/pavlick/# loadkeys ru
Loading /usr/share/kbd/keymaps/i386/qwerty/ru.map.gz

root@pc:/home/pavlick/# zcat /usr/share/kbd/keymaps/i386/qwerty/ru.map.gz
# ru-uni_ct_sh.kmap is a Russian UTF-8 keymap for a 102 key keyboard.

unicode_start Cyr_a8x16.psfu
# также пробовал setfont Cyr_a8x16.psfu
Оно вроде как и работает (кириллицей можно писать в консоле), но как-то всё криво: printf 'й' > file создаёт 3 байтовый файл (содержание не смотрел, но это явно не то, чего я ожидаю).

Где я чего-то не понимаю? По идее, шрифт не должен влиять на размер файла, я ведь выбрал раскадку с utf-8, не так ли?

 ,

pavlick ()

Добавить префикс для поиска интерпретатора

Привет. В исполняемых файлах зашита инофмация с абсолютными путями к загрузчику/интерпретатору (/lib64/ld-linux-x86-64.so, #!/bin/bash). Можно ли задать какой-то префикс, который будет прилепляться к абсолютному путю во время поиска? Например в консоле (псевдокоманда): # setprefix /sandbox; ./bash_script, и скрипт затребует /sandbox/bin/bash. Сомневаюсь, но вдруг есть какие-то варианты. Править исполняемые файлы - не вариант.

 ,

pavlick ()

Консоль поломалась

Привет, пытаюсь собрать LFS по инструкции. Быстро запарившись компилировать кучу софта, я решил немного автоматизировать процесс (создать скрипт). Но bash, в котором я произвожу все манипуляции, стартует таким образом:

lfs:~$ cat .bash_profile 
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash

lfs:~$ cat .bashrc
set +h
umask 022
LFS=/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL LFS_TGT PATH
В результате этого я не могу написать нормально скрипт (не происходит pathname expansion в скрипте, не могу создать файл - ругается на права доступа, ...). Я подумал, что дело в каких-то переменных окружения, объявил кучу всяких из полноценной консоли - не помогло. Ребята, навскидку - как подчинить консоль? Предвосхищая вопросы - нет, на сборку LFS меня побудила не наркозависимость и не скудная личная жизнь ))

 ,

pavlick ()

Альтернатива midnight commander

Привет, что можно попробовать взамен? Требования - mc слишком тяжелый, хотелось бы что-то проще:
* консольный
* без встроенных редакторов
* навигация в стиле emacs
* ну и назначить несколько клавиш на - открыть в редакторе/readelf/execute/...

 

pavlick ()

Продление жизни rvalue 2

По первой части - жестко туплю, удалил.

Там ссылка на предложенные правки http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0727r0.html (её и в прошлой теме скидывали), я по ним пробежался и чего-то не въехал:

The third context is when a reference is bound to a temporary object. [ Footnote: The same rules apply to initialization of an initializer_list object (8.6.4) with its underlying temporary array. ] The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained through one of the following:
...
a const_cast (8.2.11 [expr.const.cast]), static_cast (8.2.9 [expr.static.cast]), dynamic_cast (8.2.7 [expr.dynamic.cast]), or reinterpret_cast (8.2.10 [expr.reinterpret.cast]) converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,
...

т.е. S &&s = static_cast<S>(Q), при наличии у Q operator S() - так делать нельзя? Бредом попахивает, но к чему эти слов про user-defined conversion.

 

pavlick ()

segmentation fault

Привет, x32, вот такой выхлоп от gcc -S

.LLSDACSE1:
	.byte 0x1
	.byte 0
	.align 4
        .long DW.ref._ZTI14Fake_Exception-.

DW.ref._ZTI14Fake_Exception:
	.long _ZTI14Fake_Exception
	.hidden DW.ref._ZTI9Exception
	.weak DW.ref._ZTI9Exception
        .section .data.DW.ref._ZTI9Exception,"awG",@progbits,DW.ref._ZTI9Exception,comdat

_ZTI14Fake_Exception:
	.long _ZTVN10__cxxabiv117__class_type_infoE+8
	.long _ZTS14Fake_Exception
	.weak _ZTS14Fake_Exception
        .section .rodata._ZTS14Fake_Exception,"aG",@progbits,_ZTS14Fake_Exception,comdat
пытаюсь под gdb прочитать адрес _ZTI14Fake_Exception::_ZTVN10__cxxabiv117__class_type_infoE+8
(gdb) x/1aw 0x401743      # .LLSDACSE1+4
0x401743:       0x190000
(gdb) x/1aw 0x190000
0x190000:       Cannot access memory at address 0x190000
модуль загружен в память по адресу 0x400000. Что я не так делаю?
При этом, адрекс _ZTVN10__cxxabiv117__class_type_infoE+8 == 0x402ed8 (посмотрел по символам модуля+адрес загрузки+8).

 ,

pavlick ()

Динамические библиотеки, конспект

Привет. Так вышло, что пришлось основательно разобраться в теме и пока память свежа изложил всё в виде небольшой памятки. Удобно по прошествии некоторого времени освежить память прочитав небольшой конспект. Вообще, по-хорошему, блог что ли какой завести )). Просьба - не флудить, ссылки/комментарии/дополнения по теме приветствуются. ЗЫ: подразумевается, что либы -fpic

1. Утилиты readelf, objdump. Читать man elf, man ld.so. N в именах структор
   подразумевает 32 или 64.
2. Структура ELF файла:
   1. заголовок (смещение 0, struct ElfN_Ehdr). Readelf::ELF Header
   2. program header table (массив struct ElfN_Phdr). Содержит информацию о том
      как отображать секции в память процесса. Readelf::Program Headers
   3. section header table (массив struct ElfN_Shdr). Readelf::Section Headers
3. link_map   
3.1. Загруженные в память модули попадают в список (массив) из struct link_map.
     Списков может быть много, каждый список - "пространство имён". Для
     загрузки модулей в неглобальный список (создание нового) используется
     dlmopen().
3.1. Получать link_map модуля через dlinfo() или dladdr1():
     [--code--]
     #define _GNU_SOURCE
     #include <link.h>
     #include <dlfcn.h>
     #include <stdio.h>
     int main()
     {
        static char addr_in_mod;
        Dl_info __info;
        struct link_map *lm;
        if(dladdr1(&addr_in_mod, &__info, (void*)&lm, RTLD_DL_LINKMAP) != 0) {
           printf("link_map:\n");
           struct link_map *i = lm;
           for(; i->l_prev != NULL; i = i->l_prev);
           for (; i != NULL; i = i->l_next)
              printf("addr diff=%p  name=%s%s",(void*)i->l_addr,  i->l_name, i==lm?"  <--cur\n":"\n");
        }
     }
     //output:
     //link_map:
     //addr diff=0x41f000  name=  <--current module
     //addr diff=0xb7fc4000  name=linux-gate.so.1
     //addr diff=0xb7fa3000  name=/lib/libdl.so.2
     //addr diff=0xb7dc5000  name=/lib/libc.so.6
     //addr diff=0xb7fc6000  name=/lib/ld-linux.so.2
     [/--code--]
3.2. Во время переразмещений символ ищется в модулях указанных в link_map
     списке начиная от начала списка т.е. порядок важен, "gcc -ls1 -ls2"
     libs1.so находится в списке раньше, чем libs2.so.
3.3. При добавлении библиотеки через LD_PRELOAD, она попадает перед остальными
     разделяемыми библиотеками в глобальном link_map списке.
3.4. Опция RTLD_DEEPBIND для dlopen - собственные символы модуля приоритетнее
     символов из вышестоящих в link_map списке модулей.
     Собственные символы загружаемой библиотеки содержат:
      1. символы из самой загружаемой библиотеке
      2. символы из библиотек, которые были слинкованы с загружаемой из
         командной строки (у первых приоритет выше).
3.5. При загрузки через dlopen, библиотеки добавленные с флагом RTLD_GLOBAL
     имеют приоритет над RTLD_LOCAL, не смотря на то, что находятся в link_map
     списке позже (не относится к получению void f() через dlsym()). Например:
     [--code--]
     // предоставляет void f(), ссылается на void f().
     dlopen("lib1.so", RTLD_LOCAL);
     // предоставляет void f().
     dlopen("lib2.so", RTLD_GLOBAL);
     // при ленивом переразмещении, lib1.so будет ссылаться на lib2.so::f().
     [/--code--]
4. RTLD_GLOBAL - символы из загруженного модуля будут участвовать в
   переразмещениях для заргуженных в дальнейшем библиотек. RTLD_LOCAL - не будут.
   Если lib2.so линкуется с lib1.so через командную строку
   "gcc -fpic -shared -l2 s.c -o lib1.so", то видимость символов из lib2.so
   наследуется от видимости символов из lib1.so:
   [--code--]
   dlopen("./lib1.so", RTLD_LAZY|RTLD_GLOBAL);    // символы из lib2.so глобальные
   dlopen("./lib1.so", RTLD_LAZY|RTLD_LOCAL);     // символы из lib2.so локальные
   [/--code--]
   Если lib2.so подгружается из lib1.so через dlopen(), то видимость символов
   из lib2.so контролируется флагом dlopen() при загрузке lib2.so. Способ
   загрузки (через командную строку или dlopen) и флаг для dlopen при
   загрузки lib1.so значения не имеет.
5. Переразмещение (relocation).
5.1. Переразмещение - процесс соединения символьной ссылки с символьным
     определением.
     Переразмещение: ленивое - загрузчик вызывается при ссылке на символ, и
     ненеленивое - переразмещение при загрузке. Переразмещение переменных всегда
     неленивое.
5.2. Символы, требующие переразмещения, содержатся в .rel... секциях. В них
     находятся ElfN_Rel структуры.
     [--code--]
     typedef struct {
         Elf32_Addr r_offset;    \\ адрес внесения правки (адрес в GOT, например. readelf::Offset).
         uint32_t   r_info;      \\ содержит тип переразмещения и индекс в таблице символов (массив Elf32_Sym[]).
     } Elf32_Rel;
     typedef struct {
         uint32_t      st_name;   \\ индекс в таблице строк. Т.е. сопостовляет символ с Си строкой.
         Elf32_Addr    st_value;  \\ адрес символа в текущем модуле (readelf::Sym.Value).
         uint32_t      st_size;
         unsigned char st_info;
         unsigned char st_other;
         uint16_t      st_shndx;
     } Elf32_Sym;
     [/--code--]
5.3. Механизм обращения к переменным (требующим переразмещений):
     1. линкер на старте правит .got секцию, она начинает указывать на нужные
        данные.
     2. ссылка на переменную в коде (в .text секции):
          [--code--]
          call   44c <__x86.get_pc_thunk.ax>  # получаем в eax адрес следующей инструкции
          add    $0x1bcb,%eax                 # в eax адрес .got секции
          mov    0x14(%eax),%edx              # отступ от края .got на адрес переменной,
                                              # разыменовываем в edx
          [/--code--]
5.4. Механизм обращения к функциям, для пример - exfn():
     1. ссылка на exfn() в коде (в .text секции)
     2. переход на "трамплин" в .plt секции - plt@exfn()
     3. переход на разыменованный указатель из .got.plt, если переразмещение
        уже было произведено, то попадаем на exfn(), иначе:
        3.1. возврат в plt@exfn(), в стек кладётся смещение в .rel.plt
             секции Elf32_Rel структуры и указатель на link_map список
        3.2. вызов ld.so, правится указатель в .got.plt
        3.3. переход на exfn().
6. .dynamic секция может быть прочитана из программы через массив _DYNAMIC[],
   который содержит struct ElfN_Dyn, автоматически заполняется линкером.
7. Экспортируемые символы из elf модуля указываются в .dynsym секции.
8. -rdynamic опция линкера (для исполняемого ELF) - символы из exe, которые не
   были востребованы библиотеками, указанными в командной строке, не
   экспортируются (не указываются в .dynsym секции) и не участвуют в
   переразмещениях в библиотеках, которые подргружаются через dlopen. Данная
   опция заставляет линкер помещать в таблицу все функции.
9. Управление экспортом из модуля
   * Управление экспортом по умолчанию:
     gcc -fvisibility=default
     -fvisibility=hidden
     -fvisibility=internal
     -fvisibility=protected
   * Управление экспортом посимвольно:
     __attribute__ ((visibility ("hidden")));
     __attribute__ ((visibility ("hidden")))
   * Для группы:
     #pragma GCC visibility push(hidden)
     ...
     #pragma GCC visibility pop
   * static и анонимные namespace
   * Управление эспортом через export map, через опцию --version-script

 , , ,

pavlick ()

Управление моментом разрушения объекта

Привет. Нужно - задать необходимый порядок вызова деструкторов. Рабочий ли вариант:

struct S {
   const char *c;
   S(const char *c): c{c} {}
   ~S() {cout << c << endl;}
};

S &g1() {
   static S s{"g1"};
   return s;
}
S &g2() {
   static S s{"g2"};
   return s;
}
int main() {
   g1(); // создаём g1::S
   g2(); // создаём g2::S
   return 0;
}
Т.е создаю g1::S раньше g2::S, деструкторы в обратном порядке. Что смущает: может ли компилятор при каких-нибудь (не запрещено ли ему в принципе?) условиях заооптимизировать бесполезный на его взгляд вызов g1()/g2()?

 

pavlick ()

RSS подписка на новые темы