❌ About FreshRSS

Reading view

There are new articles available, click to refresh the page.

Segmentation fault in Ada inline assembler [duplicate]

I'm taking my first steps in Ada and attempting to write a package which manipulates the CPUID instruction. I found some sequences on the OSDev wiki here for checking the EFLAGS.ID bit that I'm attempting to modify into an Ada function using inline assembler, but I'm running into a persistent segfault when trying to run it. First, the package spec & body:

-- Specification file: Cpuid.ads --

with Standard_Types; use Standard_Types;

package Cpuid is
    function Is_Supported return Boolean;

end Cpuid;

-- Body file: Cpuid.adb --

with System.Machine_Code; use System.Machine_Code;

package body Cpuid is

    function Is_Supported return Boolean is
        HT  : constant Character := Character'Val(16#09#);
        LF  : constant Character := Character'Val(16#0A#);
        EAX : Unsigned_32 := 16#0000_0000#;
        Asm ("pushfq"                    & LF & HT &
             "pushfq"                    & LF & HT &
             "popq    %%rax"             & LF & HT &
             "xorq    0x00200000, %%rax" & LF & HT &
             "pushq   %%rax"             & LF & HT &
             "popfq"                     & LF & HT &
             "pushfq"                    & LF & HT &
             "popq    %%rax"             & LF & HT &
             "xorq    (%%rsp), %%rax"    & LF & HT &
             "popfq"                     & LF & HT &
             "andq    0x00200000, %%rax" & LF & HT &
             "movl    %%eax, %0",
             Outputs  => Unsigned_32'Asm_Output ("=g", EAX),
             Volatile => True);
        if EAX /= 16#0000_0000# then 
            return True; 
            return False; 
        end if;
    end Is_Supported;

end Cpuid;

The Cpuid.Is_Supported function is called by a main program which looks like this:

with Ada.Text_IO;    use Ada.Text_IO;
with Standard_Types; use Standard_Types;
with Cpuid;

procedure Cpuid_Check is
    Some_Int : Unsigned_32 := 0;
    if Cpuid.Is_Supported then
        Put_Line ("CPUID instruction supported on this CPU.");
        Put_Line ("CPUID instruction not supported.");
    end if;
end Cpuid_Check;

Note that the Standard_Types import is just a spec-only package consisting of handwritten type definitions for Unsigned_8, Unsigned_16, and Unsigned_32.

When I attempt to run this program, the program fails with PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION. Using GDB allows me to trace the error to a SIGSEGV, but I am not able to trace the violation further to a particular instruction issuance. The full debugger output is as follows:

Temporary breakpoint 14, 0x00000000004016e0 in cpuid_check ()
[program stopped: breakpoint-hit]
(gdb) -exec-next
Single stepping until exit from function _ada_cpuid_check,
which has no line number information.
[program running]

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401ede in cpuid.is_supported ()
[program stopped: signal-received]
(gdb) -exec-next
Single stepping until exit from function cpuid__is_supported,
which has no line number information.
[program running]

Program received signal SIGSEGV, Segmentation fault.
0x00007ffc4d3473f9 in KERNEL32!IsBadReadPtr () from C:\Windows\System32\kernel32.dll
[program stopped: signal-received]

I've checked to ensure that I'm leaving the stack "as I found it", which, to the best of my ability, appears to be the case - the same number of pushes and pops occur within the inline assembly section. I've also rearranged the assembly sequence into src, dest format, as my reading on GAS indicates that is the syntax used. In the process, however, I bamboozled myself - I'm more used to Intel/NASM syntax, and GAS looks like a mess in comparison.

Is there a way to rectify this function so that it functions properly?

EDIT: Here is the disassembly dump from GDB, as noted in the comments:

(gdb) disas
Dump of assembler code for function cpuid__is_supported:
   0x0000000000401ec4 <+0>: push   %rbp
   0x0000000000401ec5 <+1>: mov    %rsp,%rbp
   0x0000000000401ec8 <+4>: sub    $0x10,%rsp
   0x0000000000401ecc <+8>: movb   $0x9,-0x1(%rbp)
   0x0000000000401ed0 <+12>:    movb   $0xa,-0x2(%rbp)
   0x0000000000401ed4 <+16>:    movl   $0x0,-0x8(%rbp)
   0x0000000000401edb <+23>:    pushfq 
   0x0000000000401edc <+24>:    pushfq 
   0x0000000000401edd <+25>:    pop    %rax
=> 0x0000000000401ede <+26>:    xor    0x200000,%rax
   0x0000000000401ee6 <+34>:    push   %rax
   0x0000000000401ee7 <+35>:    popfq  
   0x0000000000401ee8 <+36>:    pushfq 
   0x0000000000401ee9 <+37>:    pop    %rax
   0x0000000000401eea <+38>:    xor    (%rsp),%rax
   0x0000000000401eee <+42>:    popfq  
   0x0000000000401eef <+43>:    and    0x200000,%rax
   0x0000000000401ef7 <+51>:    mov    %eax,%eax
   0x0000000000401ef9 <+53>:    mov    %eax,-0x8(%rbp)
   0x0000000000401efc <+56>:    cmpl   $0x0,-0x8(%rbp)
   0x0000000000401f00 <+60>:    je     0x401f09 <cpuid__is_supported+69>
   0x0000000000401f02 <+62>:    mov    $0x1,%eax
   0x0000000000401f07 <+67>:    jmp    0x401f0e <cpuid__is_supported+74>
   0x0000000000401f09 <+69>:    mov    $0x0,%eax
   0x0000000000401f0e <+74>:    nop
   0x0000000000401f0f <+75>:    nop
   0x0000000000401f10 <+76>:    add    $0x10,%rsp
   0x0000000000401f14 <+80>:    pop    %rbp
   0x0000000000401f15 <+81>:    retq   
   0x0000000000401f16 <+82>:    nop
   0x0000000000401f17 <+83>:    nop
   0x0000000000401f18 <+84>:    nop
   0x0000000000401f19 <+85>:    nop
   0x0000000000401f1a <+86>:    nop
   0x0000000000401f1b <+87>:    nop
   0x0000000000401f1c <+88>:    nop
   0x0000000000401f1d <+89>:    nop
   0x0000000000401f1e <+90>:    nop
   0x0000000000401f1f <+91>:    nop
End of assembler dump.

Ada-based applications in Android?

I have been struggling to make my Ada program run on Android (through a Java native interface), with so far no results. As I understand it, the generic Linux GCC compiler will not make the job, because even if it targets the right architecture (arm64), the compiler toolchain needs to be built using Android “binutils”. Is it like that (or even more complex than that)?
In any case, frustrated by the fact that my SAL generated with gprbuild and GCC will refuse to work (at least with the FSF compiler), I posted my issue on Stack Overflow, and somebody threw the idea of using LLVM instead. So I was wondering if the Gnat LLVM project could help me here.
I started reading about LLVM, and I find it a bit hard to grasp. My current understanding is that I could use it to compile Ada into IR code, that would be then compiled into machine code for an specific architecture, without requiring the installation of a particular cross compiler. Is that right?
Is it theoretically feasible to generate a SAL with a Java interface for Android using this toolchain? And if so, how?
Otherwise, could somebody expose the purpose and/or usages of Gnat LLVM?

Before you react, please know that my understanding of compilers is very limited…
In case you are curious about what I am doing, my project is open source, you can take a look at it here:

3 posts - 2 participants

Read full topic

[ANN] Qplt (Quick Plot)

Seen on c.l.a:

I have created Qplt (Quick Plot), an Ada-GUI program to quickly produce a plot of a data set, and make it publicly available in hopes that it might prove useful. The program automatically selects axis ranges and tick intervals. The user may select whether points, lines, or both are plotted, and supply a title and axis labels.

Qplt is available at


10 posts - 4 participants

Read full topic

usb_embedded + RP2040

Hello! I am considering using Ada for my bachelor's thesis since I've had nice experiences before (I've moved to GNAT Studio and everything is alright now).

Specifically, I am implementing a Forth interpreter, which means I (obviously) need to get data from the user and you can guess by the title I am doing that over USB.

https://pico-doc.synack.me/#usb_device_controller points me to the usb_embedded crate and its usb-echo example... the problem is that I can't make it to show anything other than the string I entered as per the example (or see anything in picocom or minicom). I am using Picoprobe + OpenOCD (external, I couldn't figure out how to make it also take -f interface/cmsis-dap.cfg) + gdb from inside GNAT Studio, if that helps.

To cite the example (with the only changes being formatting and the USB stack details:

``` with RP.Device; with RP.Clock; with Pico;

with USB.Device.Serial; with USB.Device; with USB; with HAL; use HAL;

procedure Hello_Pico is Fatal_Error : exception; Max_Packet_Size : constant := 64;

USB_Stack : USB.Device.USB_Device_Stack (Max_Classes => 1); USB_Serial : aliased USB.Device.Serial.Default_Serial_Class (TX_Buffer_Size => Max_Packet_Size, RX_Buffer_Size => Max_Packet_Size);

use type USB.Device.Init_Result; Status : USB.Device.Init_Result;

Message : String (1 .. Max_Packet_Size); Length : HAL.UInt32; begin RP.Clock.Initialize (Pico.XOSC_Frequency);

if not USB_Stack.Register_Class (USB_Serial'Unchecked_Access) then raise Fatal_Error with "Failed to register USB Serial device class"; end if;

Status := USB_Stack.Initialize (Controller => RP.Device.UDC'Access, Manufacturer => USB.To_USB_String ("Something"), Product => USB.To_USB_String ("Here"), Serial_Number => USB.To_USB_String ("1337"), Max_Packet_Size => Max_Packet_Size);

if Status /= USB.Device.Ok then raise Fatal_Error with "USB stack initialization failed: " & Status'Image; end if;


loop USB_Stack.Poll;

 if USB_Serial.List_Ctrl_State.DTE_Is_Present then USB_Serial.Read (Message, Length); if Length > 0 then USB_Serial.Write (RP.Device.UDC, Message (1 .. Natural (Length)), Length); end if; end if; 

end loop; end Hello_Pico; ```

I understand the logic behind this, however I don't get where I should do USB_Serial.Write(RP.Device.UDC, "> ", Length);. Nothing is displayed if I add it before the loop, inside it on either part of the USB_Stack.Poll; line OR in either of the ifs. I really feel like I am missing one key part.

Additionally, every (and I mean every) embedded project of any kind on Ada (at least on GitHub, although my Google-fu and DDG-fu showed no results either) has everything BUT an USB example. I would really, really like to avoid C and not give up on this beautiful language, so can someone help me? I really feel like I'm not seeing something so obvious.

Thank you and have a beautiful [insert time of day]!

submitted by /u/uneven-shiver
[link] [comments]

Ada2012: Assertion_Policy

According Ada2012 RM Assertion_Policy:

10.2/3 A pragma Assertion_Policy applies to the named assertion aspects in a specific region, and applies to all assertion expressions specified in that region. A pragma Assertion_Policy given in a declarative_part or immediately within a package_specification applies from the place of the pragma to the end of the innermost enclosing declarative region. The region for a pragma Assertion_Policy given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.

This means that if I have a package hierarchy as per the following example:

    │   └───GrandSon

And if I define the pragma Assertion_Policy at Root package specification, it will affect to the whole package hierarchy right?