GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 10.02.21 09:39
Оценка:
Всем привет. Не сильно надеюсь, что будет ответ, но вдруг

Играюсь с GraalVM и прямому доступу к линуксу.
С вызовом функций с простыми типами, как mmap, strerror, ну и всяким прочим open/close/write/read проблем добраться и использовать нет.

Проблемы приши после попыток дотянуться до ioctl, а именно когда пришлось передавать стуктуры и указатели на структуру.

Скупая документация на GraalVM фактически сводится к одному примеру , который не особо помог с ответом.

А нужно протянуть в java что-то примерно такое:
typedef union my_union
{
  uint8_t  bb;
  uint16_t ww;
  uint8_t  arr[32]; // <-- Проблема раз, как заалоцировать
} my_union;

typedef struct my_struct
{
  char cc;
  int size;
  union my_union *data ; // <-- Проблема как создать и присобачить указатель на union тут
} my_struct;


В Graal это привращается во что-то такое (оно даже компиляется и запускается):
@CStruct("my_union")
    public interface my_union extends PointerBase {
        @CField("bb")
        byte getBb();

        @CField("bb")
        void setBb(byte b);

        @CField("ww")
        short getWw();

        @CField("ww")
        void setWw(short word);

        @CFieldAddress("arr")
        Pointer getBlock(); // Какой тут тип должен быть?
    }

@CStruct("my_struct")
    public interface my_struct extends Pointer {
        @CField("сс")
        byte getСс();

        @CField("сс")
        void setСс(byte rw);
   

        @CField("size")
        int getSize();

        @CField("size")
        void setSize(int size);


        @CFieldAddress("data")
        CIntPointer getData(); // Какой тут тип должен быть? И как установить указатель на my_union
    }

При передаче в таком виде, оно падает с ошибкой ioctl failed: -1

Соответственно вопросы:
1. Как правильно объявить структуры в GraalVM
2. Как правильно инициализировать и установить указатели.

Либо хотя бы как отдэбажить что native-image генерит(оно в момент трет исходики нативные) и что в ioctl пришло. Заранее благодарен за ответы.
Отредактировано 10.02.2021 9:44 Infernal . Предыдущая версия . Еще …
Отредактировано 10.02.2021 9:42 Infernal . Предыдущая версия .
Re: GraalVM + native-image + posix + struct/union
От: StanislavK Великобритания  
Дата: 10.02.21 10:14
Оценка: 1 (1)
Здравствуйте, Infernal, Вы писали:

I>Играюсь с GraalVM и прямому доступу к линуксу.

Мне кажется, что просто использовать CStruct для union не получится.
По поводу указателя, есть аннотация CPointerTo, мне кажется она как раз для этого.

JNI не подходит?
Re[2]: GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 10.02.21 10:54
Оценка:
Здравствуйте, StanislavK, Вы писали:

SK>Здравствуйте, Infernal, Вы писали:


I>>Играюсь с GraalVM и прямому доступу к линуксу.

SK>Мне кажется, что просто использовать CStruct для union не получится.
SK>По поводу указателя, есть аннотация CPointerTo, мне кажется она как раз для этого.

SK>JNI не подходит?

Тут как раз от него хочется отказаться.
Под JVM вполне все прекрасно выходит под сделать под JNA.
Сейчас осваиваю компиляцию того же кода, только в натив без всяких дополнительных нативных библиотек.

CPointerTo я видел, но с ходу не понял как его можно применить. Эта аннотация на интефейс, а не на поле в виде указателя. Сейчас вроде начало доходить, спасибо, попробую.

Походу придется копать в натив. По идее, зная размеры структур, оффсеты полей (это можно достать прямо через функции грааля, дабы не хардкодить), можно через malloc/free все замутить, если через аннотации не получится.
Re[3]: GraalVM + native-image + posix + struct/union
От: StanislavK Великобритания  
Дата: 10.02.21 14:35
Оценка:
Здравствуйте, Infernal, Вы писали:

I>Здравствуйте, StanislavK, Вы писали:


I>CPointerTo я видел, но с ходу не понял как его можно применить. Эта аннотация на интефейс, а не на поле в виде указателя. Сейчас вроде начало доходить, спасибо, попробую.

Тут, как я понимаю, довольно много примеров:
https://github.com/oracle/graal/tree/master/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers

В substratevm много чего есть.
Re[4]: GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 11.02.21 05:40
Оценка:
Здравствуйте, StanislavK, Вы писали:

SK>Здравствуйте, Infernal, Вы писали:


I>>Здравствуйте, StanislavK, Вы писали:


I>>CPointerTo я видел, но с ходу не понял как его можно применить. Эта аннотация на интефейс, а не на поле в виде указателя. Сейчас вроде начало доходить, спасибо, попробую.

SK>Тут, как я понимаю, довольно много примеров:
SK>https://github.com/oracle/graal/tree/master/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers

SK>В substratevm много чего есть.


Да, это я видел, маппинг некоторых функций, которые им самим похоже потребовались. Кое что оттуда вынес. Но с конкретной задачей это не помогло.

Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.
Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.

Начинаю копать в сторону malloc/free.
Re[5]: GraalVM + native-image + posix + struct/union
От: StanislavK Великобритания  
Дата: 11.02.21 09:17
Оценка:
Здравствуйте, Infernal, Вы писали:

I>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.

Мне кажется, что тогда для union надо задавать offset для каждого поля, иначе я не понимаю, как оно может работать.

I>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.

А вот это: https://www.graalvm.org/reference-manual/native-image/DebugInfo/
ну и потом с dbg.
Re[5]: GraalVM + native-image + posix + struct/union
От: maxkar  
Дата: 15.02.21 17:11
Оценка:
Здравствуйте, Infernal, Вы писали:

I>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.

Правильно — это сколько? И как вы победили массив? В вашем примере у my_union размер должен быть 32 байта. И меня очень смущает стрелочка на arr в вопросе про аллокацию. Это же C, тот конкретный arr не нужно вообще аллоцировать. Стрелочка должна показывать на сам struct. Или в graal какие-то секретные аннотации есть?

I>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.

Если только посмотреть — есть strace. Если еще пощупать — уже предложили gdb. Можно что-нибудь визуальное поверх него, например — ddd. Если инструментов нет — устанавливайте соответствующие пакеты, они почти во всех дистрибутивах должны быть.
Re[6]: GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 15.02.21 18:35
Оценка:
Здравствуйте, maxkar, Вы писали:

M>Здравствуйте, Infernal, Вы писали:


I>>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.

M>Правильно — это сколько? И как вы победили массив? В вашем примере у my_union размер должен быть 32 байта. И меня очень смущает стрелочка на arr в вопросе про аллокацию. Это же C, тот конкретный arr не нужно вообще аллоцировать. Стрелочка должна показывать на сам struct. Или в graal какие-то секретные аннотации есть?

Проверил, в момент компиляции native-image все нормально все аллоцируется, грааль размер получает правильный.

I>>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.

M>Если только посмотреть — есть strace. Если еще пощупать — уже предложили gdb. Можно что-нибудь визуальное поверх него, например — ddd. Если инструментов нет — устанавливайте соответствующие пакеты, они почти во всех дистрибутивах должны быть.

Как предложил Станислав, через @CPointerTo struct/union прекрасно связались. Спасибо ему.

Пошел несколько дальше. Написал враппер в виде лайбрари на си, в котором вызываю ioctl.
Дергаю вызов одинаковых структур, с одинаковыми параметрами из си и структур из явы и сравниваю.

Размеры — одинаковые, данные — тоже. Проверял через GDB.
Единственная разница, в си указатели идут последовательно:
7ffffff150 — для структуры
7ffffff160 — для union

Для явы — нет:
5555e12a00
5555e127e0

Из Си все работает, в яве — ошибка.

Если делать то же самое под JNA, то решается как просто создаем вместо структуры Memory, заполняем и в качестве union кладем тоже Memory. Тогда все норм.
Есть подозрение, что надо тоже единый вектор памяти под структуры создавать и его передавать. Копаю дальше.
Re[7]: GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 15.02.21 19:14
Оценка:
Здравствуйте, Infernal, Вы писали:

I>Здравствуйте, maxkar, Вы писали:


Вроде разобрался. Завтра если интересно, отпишусь по результатам.
Re[8]: GraalVM + native-image + posix + struct/union
От: StanislavK Великобритания  
Дата: 17.02.21 16:15
Оценка:
Здравствуйте, Infernal, Вы писали:

I>Вроде разобрался. Завтра если интересно, отпишусь по результатам.

Ну и где результаты?
Re[9]: GraalVM + native-image + posix + struct/union
От: Infernal Россия  
Дата: 18.02.21 11:52
Оценка: 11 (2)
Здравствуйте, StanislavK, Вы писали:

SK>Здравствуйте, Infernal, Вы писали:


I>>Вроде разобрался. Завтра если интересно, отпишусь по результатам.

SK>Ну и где результаты?

Да, сорри.

Example.java
package test;

import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CLibrary;
import org.graalvm.nativeimage.c.struct.CField;
import org.graalvm.nativeimage.c.struct.CFieldAddress;
import org.graalvm.nativeimage.c.struct.CPointerTo;
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;

import java.util.Collections;
import java.util.List;

@CContext(Example.Headers.class)
@CLibrary("c")
public class Example {
    public static class Headers implements CContext.Directives {
        @Override
        public List<String> getHeaderFiles() {
            return Collections.singletonList("\"[path_to]/my_header.h\"");
        }
    }

    @CPointerTo(MyUnion.class)
    public interface MyUnionPtr extends PointerBase {
        MyUnion read();
        void write(MyUnion data);
    }



    /*
    typedef union my_union
    {
        uint8_t  bb;
        uint16_t ww;
        uint8_t  arr[32];
    } my_union;
     */

    @CStruct("union my_union")
    public interface MyUnion extends PointerBase {
        @CField("bb")
        byte getByte();

        @CField("bb")
        void setByte(byte b);

        @CField("ww")
        short getWord();

        @CField("ww")
        void setWord(short word);

        @CFieldAddress("arr")
        Pointer getArray();
    }


    /*
    typedef struct my_struct
    {
        char cc;
        int size;
        union my_union *data ;
    } my_struct;
     */
    @CStruct("my_struct")
    public interface MyStruct extends PointerBase {
        @CField("cc")
        byte getChar();

        @CField("cc")
        void setChar(byte b);

        @CField("size")
        int getSize();

        @CField("size")
        void setSize(int size);

        @CFieldAddress("data")
        MyUnionPtr getData();
    }
}


ExampleIoctl.java
package test;

import org.graalvm.nativeimage.UnmanagedMemory;
import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CFunction;
import org.graalvm.nativeimage.c.function.CLibrary;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.word.PointerBase;

import java.util.Collections;
import java.util.List;

@CContext(ExampleIoctl.Headers.class)
@CLibrary("c")
public class ExampleIoctl {
    public class Headers implements CContext.Directives {
        public List<String> getHeaderFiles() {
            return Collections.singletonList(
                    "\"/usr/include/linux/ioctl.h\""
            );
        }
    }

    private static class Delegate {
        @CFunction(transition = CFunction.Transition.NO_TRANSITION)
        public static native int ioctl(int fd, long command, PointerBase ptr);
    }

    public static void static void main(String[] args) {
        Example.MyStruct struct = UnmanagedMemory.malloc(
                SizeOf.get(Example.MyStruct.class)
        );

        Example.MyUnion union = UnmanagedMemory.malloc(
                SizeOf.get(Example.MyUnion.class)
        );

        try {
            // TODO fill values for struct/union

            // Set ptr
            struct.getData().write(union);

            Delegate.ioctl([file_id], [command],struct);

        } finally {
            UnmanagedMemory.free(union);
            UnmanagedMemory.free(struct);
        }

    }

}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.