- difference between i386:x64-32 vs i386 vs i386:x86_64
- 2 Answers 2
- Native transports
- Saved searches
- Use saved searches to filter your results more quickly
- License
- platformio/platform-linux_x86_64
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- Погружение в x86-64 SystemV ABI
- Демонстрационная задача
- Среда разработки
- Очень краткая справка
difference between i386:x64-32 vs i386 vs i386:x86_64
Can someone explain the difference between the three architectures? Actually when I built a 64-bit application in Linux, I got a link error saying:
skipping incompatible library.a when searching for library.a
a.o: file format elf32-x86-64 architecture: i386:x64-32, flags 0x00000011: HAS_RELOC, HAS_SYMS start address 0x00000000
Note that static libraries are generally far more trouble than they are worth. Use dynamic libraries, with an $ -relative -rpath if you really need to and don’t need setuid or any other capabilities .
2 Answers 2
There are 3 common ABIs usable on standard Intel-compatible machines (not Itanium).
- The classic 32-bit architecture, often called «x86» for short, which has triples like i586-linux-gnu . Registers and pointers are both 32 bits.
- The 64-bit extension originally from AMD, often called «amd64» for short, which has GNU triple of x86_64-linux-gnu . Registers and pointers are both 64 bits.
- The new «x32» ABI, with a triple of x86_64-linux-gnux32 . Registers are 64 bits, but pointers are only 32 bits, saving a lot of memory in pointer-heavy workflows. It also ensures all the other 64-bit only processor features are available.
Each of the above has its on system call interface, own ld.so , own complete set of libraries, etc. But it is possible to run all 3 on the same kernel.
On Linux, their loaders are:
% objdump -f /lib/ld-linux.so.2 /lib64/ld-linux-x86-64.so.2 /libx32/ld-linux-x32.so.2 /lib/ld-linux.so.2: file format elf32-i386 architecture: i386, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x00000a90 /lib64/ld-linux-x86-64.so.2: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x0000000000000c90 /libx32/ld-linux-x32.so.2: file format elf32-x86-64 architecture: i386:x64-32, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x00000960
Now, if you’re getting the message about «skipping incompatible library», that means something is messed up with your configuration. Make sure you don’t have bad variables in the environment or passed on the command line, or files installed outside of your package manager’s control.
Native transports
Netty provides the following platform specific JNI transports:
These JNI transports add features specific to a particular platform, generate less garbage, and generally improve performance when compared to the NIO based transport.
Using the native transports
Note that you must specify the proper classifier for the dependency to ensure that the corresponding native libraries are included.
Using the Linux native transport
Because the native transport is compatible with the NIO transport, you can just do the following search-and-replace:
- NioEventLoopGroup → EpollEventLoopGroup
- NioEventLoop → EpollEventLoop
- NioServerSocketChannel → EpollServerSocketChannel
- NioSocketChannel → EpollSocketChannel
Because the native transport is not part of the Netty core, you need to pull the netty-transport-native-epoll as a dependency in your Maven pom.xml , or equivalent for your build system:
dependencies> dependency> groupId>io.nettygroupId> artifactId>netty-transport-native-epollartifactId> version>$ version> classifier>linux-x86_64classifier> dependency> . dependencies>
In the above, the classifier is linux-x86_64 , which means the native binaries included in the dependency are compiled for Linux, running on 64-bit x86 CPUs. Other CPU architectures, and some specific Linux distributions, will need different classifiers.
Note: The official Linux builds are all linked against GLIBC. This means operating systems that use Musl as their libc implementation are not supported by the official builds of the Netty native transports. If you wish to use the Netty native transports on unsupported CPU architectures or libc implementations, you will need to make your own build. See below for how to do that.
For using the native transport in a sbt project, please add line below to your libraryDependencies :
"io.netty" % "netty-transport-native-epoll" % "$" classifier "linux-x86_64"
Using the MacOS/BSD native transport
Because the native transport is compatible with the NIO transport, you can just do the following search-and-replace:
- NioEventLoopGroup → KQueueEventLoopGroup
- NioEventLoop → KQueueEventLoop
- NioServerSocketChannel → KQueueServerSocketChannel
- NioSocketChannel → KQueueSocketChannel
Because the native transport is not part of the Netty core, you need to pull the netty-transport-native-kqueue as a dependency in your Maven pom.xml :
dependencies> dependency> groupId>io.nettygroupId> artifactId>netty-transport-native-kqueueartifactId> version>$ version> classifier>osx-x86_64classifier> dependency> . dependencies>
For using the native transport in a sbt project, please add line below to your libraryDependencies :
"io.netty" % "netty-transport-native-kqueue" % "$" classifier "osx-x86_64"
Building the native transports
If you already have the JAR file of the native transport, you should not need to build the native transport by yourself because the JAR file already contains the necessary shared library files (e.g. .so , .dll , .dynlib ) and they will be loaded automatically.
Building the Linux native transport
To build the native transport, you need to use Linux with 64-bit kernel 2.6 or higher. Please also install the required tools and libraries:
# RHEL/CentOS/Fedora: sudo yum install autoconf automake libtool make tar \ glibc-devel \ libgcc.i686 glibc-devel.i686 # Debian/Ubuntu: sudo apt-get install autoconf automake libtool make tar \ gcc
Building the MacOS/BSD native transport
To build the native transport, you need to use MacOS 10.12 or higher. Please also install the required tools and libraries:
brew install autoconf automake libtool
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Linux x86_64: development platform for PlatformIO
License
platformio/platform-linux_x86_64
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
Linux x86_64: development platform for PlatformIO
Linux x86_64 (64-bit) is a Unix-like and mostly POSIX-compliant computer operating system (OS) assembled under the model of free and open-source software development and distribution. Using host OS (Mac OS X or Linux 64-bit) you can build native application for Linux x86_64 platform.
[env:stable] platform = linux_x86_64 board = . .
[env:development] platform = https://github.com/platformio/platform-linux_x86_64.git board = . .
Погружение в x86-64 SystemV ABI
Абстракция — фундамент программирования. Многие вещи мы используем, не задумываясь об их внутреннем устройстве, и они отлично работают. Всем известно, что пользовательские программы взаимодействуют с ядром через системные вызовы, но задумывались ли вы, как это происходит на вашей машине?
Вспомним сигнатуру функции main в C:
Откуда берутся число аргументов ( argc ) и массив указателей на их строки ( argv )? Как возвращаемое значение main становится кодом возврата самого приложения?
Краткий ответ: зависит от архитектуры процессора. Увы, доступных для начинающих материалов по самой распространенной сейчас архитектуре x86-64 очень мало, и интересующиеся новички вынуждены сначала обращаться к старой литературе по 32-битным x86, которая следует другим соглашениям.
В этой статье мы попробуем исправить это и показать прямое взаимодействие с машиной и ядром Linux сразу в 64-битном режиме.
Демонстрационная задача
Для примера мы напишем расширенную версию hello world, которая может приветствовать любое количество объектов или людей, чьи имена передаются в аргументах команды.
Среда разработки
Для примера мы будем использовать Linux и GNU toolchain (GCC и binutils), как самые распространенные операционные системы и среда разработки. Писать мы будем на языке ассемблера, потому что продемонстрировать низкоуровневое взаимодействие с операционной системе из языка сколько-нибудь высокого уровня невозможно.
Очень краткая справка
Чтобы упростить понимание статьи тем, кто вообще никогда не сталкивался с ассемблером x86, я использовал только самые простые инструкции и постарался аннотировать их псевдокодом везде, где возможно. Я использую синтаксис AT&T, который все инструменты GNU используют по умолчанию. Стоит помнить, что регистры пишутся с префиксом % (например, % rax ), а константы — c префиксом $ . Например, $ 255 , $ 0xFF , $ foo — значение символа foo .
Синтаксис указателей: смещение ( база , индекс , множитель ) . Очень краткая справка:
- mov < источник >, < приемник >— копирует значение из источника (регистра или адреса) в приемник;
- push < источник >— добавляет значение из источника на стек;
- pop < приемник >— удаляет значение из стека и копирует в приемник;
- call < указатель на функцию >— вызывает функцию по указанному адресу;
- ret — возврат из функции;
- jmp < адрес >— безусловный переход по адресу (метке);
- inc и dec — инкремент и декремент;
- cmp < значение 1 >< значение 2 >— сравнение и установка флагов (например, равенство);
- je < метка >— переход на метку в случае, если аргументы cmp оказались равными.
Условные переходы и циклы реализуются через инструкции сравнения и условные переходы. Инструкции сравнения устанавливают определенные разряды в регистре флагов, команда условного перехода проверяет их и принимает решение, переходить или нет. Например, следующий цикл увеличивает значение регистра % rax , пока оно не станет равным 10, а затем копирует его в % rbx .
Для лучшего понимания ассемблера x86 я могу порекомендовать книгу Programming From the Ground Up — к сожалению, ориентированную на 32-битную архитектуру, но очень хорошо написанную и подходящую новичкам.