Olivier Bonaventure

227 papers A* 17A 22B 23C 1Misc 5Journal 109Unranked 45
YearRankTypeTitle / Venue / Authors
2025 conf
ANRW
Louis Navarre, Olivier Bonaventure
2025 J jnl
Comput. Commun. Rev.
Louis Navarre, Quentin De Coninck, Tom Barbette, Olivier Bonaventure
2025 conf
SIGCOMM (Posters and Demos)
Louis Navarre, Olivier Bonaventure
2025 conf
ANRW
Paul-Edouard Bertrand, Matthieu Baerts, Olivier Bonaventure
2024 J jnl
Comput. Commun. Rev.
Maxime Piraux, Olivier Bonaventure
2024 B conf
IFIP Networking
Nicolas Rybowski, Cristel Pelsser, Olivier Bonaventure
2024 J jnl
Proc. ACM Netw.
Marco Mellia, Peter Steenkiste, Lili Qiu, Olivier Bonaventure
2024 B conf
ICNP
Vany V. Ingenzi, Tom Barbette, Olivier Bonaventure
2024 J jnl
IEEE/ACM Trans. Netw.
François Michel, Olivier Bonaventure
2024 J jnl
PACMNET
Thomas Wirtgen, Nicolas Rybowski, Cristel Pelsser, Olivier Bonaventure
2023 J jnl
CoRR
Maxime Piraux, Olivier Bonaventure
2023 ed.
CoNEXT (Short Papers)
Dario Rossi, Stefano Secci, Olivier Bonaventure, Lili Qiu
2023 J jnl
IEEE/ACM Trans. Netw.
François Michel, Alejandro Cohen, Derya Malak, Quentin De Coninck, Muriel Médard, Olivier Bonaventure
2023 J jnl
CoRR
Louis Navarre, Olivier Pereira, Olivier Bonaventure
2023 J jnl
PACMNET
Marco Mellia, Peter Steenkiste, Lili Qiu, Olivier Bonaventure
2023 J jnl
PACMNET
Marco Mellia, Peter Steenkiste, Lili Qiu, Olivier Bonaventure
2023 J jnl
PACMNET
Marco Mellia, Peter Steenkiste, Lili Qiu, Olivier Bonaventure
2023 J jnl
CoRR
Thomas Wirtgen, Nicolas Rybowski, Cristel Pelsser, Olivier Bonaventure
2023 J jnl
CoRR
François Michel, Olivier Bonaventure
2023 Misc conf
NSDI
Thomas Wirtgen, Tom Rousseaux, Quentin De Coninck, Nicolas Rybowski, Randy Bush, Laurent Vanbever, Axel Legay, Olivier Bonaventure
2022 A conf
IMC
François Michel, Martino Trevisan, Danilo Giordano, Olivier Bonaventure
2022 conf
FIRA@SIGCOMM
Thomas Wirtgen, Olivier Bonaventure
2022 conf
StudentWorkshop@CoNEXT
Nikita Tyunyayev, Maxime Piraux, Olivier Bonaventure, Tom Barbette
2022 conf
WNS3
Nicolas Rybowski, Olivier Bonaventure
2022 conf
StudentWorkshop@CoNEXT
Louis Navarre, Nicolas Rybowski, Olivier Bonaventure
2022 J jnl
CoRR
François Michel, Alejandro Cohen, Derya Malak, Quentin De Coninck, Muriel Médard, Olivier Bonaventure
2022 J jnl
IEEE Trans. Netw. Serv. Manag.
Mathieu Jadin, Quentin De Coninck, Louis Navarre, Michael Schapira, Olivier Bonaventure
2022 J jnl
RFC
Luigi Iannone, Damien Saucez, Olivier Bonaventure
2022 A conf
IMC
Maxime Piraux, Louis Navarre, Nicolas Rybowski, Olivier Bonaventure, Benoit Donnet
2022 J jnl
Comput. Commun. Rev.
Maxime Piraux, Tom Barbette, Nicolas Rybowski, Louis Navarre, Thomas Alfroy, Cristel Pelsser, François Michel, Olivier Bonaventure
2021 conf
SIGCOMM Posters and Demos
Nicolas Rybowski, Quentin De Coninck, Tom Rousseaux, Axel Legay, Olivier Bonaventure
2021 conf
ANRW
Matthieu Baerts, Nicolas Keukeleire, Olivier Bonaventure
2021 J jnl
IEEE Commun. Mag.
Quentin De Coninck, Olivier Bonaventure
2021 conf
SIGCOMM Posters and Demos
Louis Navarre, François Michel, Olivier Bonaventure
2021 A conf
CoNEXT
Florentin Rochet, Emery Assogba, Maxime Piraux, Korian Edeline, Benoit Donnet, Olivier Bonaventure
2020 J jnl
RFC
Olivier Bonaventure, Mohamed Boucadair, Sri Gundavelli, Sunghoon Seo, Benjamin Hesmans
2020 J jnl
Comput. Commun.
Viet-Hoang Tran, Olivier Bonaventure
2020 J jnl
IEEE Commun. Stand. Mag.
Nicolas Keukeleire, Benjamin Hesmans, Olivier Bonaventure
2020 J jnl
Comput. Commun. Rev.
Olivier Bonaventure, Quentin De Coninck, Fabien Duchene, Anthony Gégo, Mathieu Jadin, François Michel, Maxime Piraux, Chantal Poncin, Olivier Tilmans
2020 J jnl
RFC
Alan Ford, Costin Raiciu, Mark Handley, Olivier Bonaventure, Christoph Paasch
2020 Misc conf
HotNets
Florentin Rochet, Emery Assogba, Olivier Bonaventure
2020 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2020 J jnl
Comput. Commun. Rev.
Ralph Holz, Marco Mellia, Olivier Bonaventure, Hamed Haddadi, Matthew Caesar, Sergey Gorinsky, Gianni Antichi, Joseph Camp, K. C. Claffy, Bhaskaran Raman, Anna Sperotto, Aline Carneiro Viana, Steve Uhlig
2020 Misc conf
HotNets
Thomas Wirtgen, Quentin De Coninck, Randy Bush, Laurent Vanbever, Olivier Bonaventure
2019 B conf
Networking
Viet-Hoang Tran, Olivier Bonaventure
2019 J jnl
CoRR
Viet-Hoang Tran, Olivier Bonaventure
2019 A* conf
INFOCOM
Mathieu Jadin, Francois Aubry, Pierre Schaus, Olivier Bonaventure
2019 J jnl
CoRR
Olivier Tilmans, Olivier Bonaventure
2019 J jnl
Comput. Commun. Rev.
Damien Saucez, Luigi Iannone, Olivier Bonaventure
2019 J jnl
CoRR
Florentin Rochet, Olivier Bonaventure, Olivier Pereira
2019 J jnl
CoRR
Nicolas Keukeleire, Benjamin Hesmans, Olivier Bonaventure
2019 conf
LCN Symposium
Olivier Bonaventure
2019 conf
TMA
Quentin De Coninck, Olivier Bonaventure
2019 A* conf
SIGCOMM
Quentin De Coninck, François Michel, Maxime Piraux, Florentin Rochet, Thomas Given-Wilson, Axel Legay, Olivier Pereira, Olivier Bonaventure
2019 B conf
Networking
François Michel, Quentin De Coninck, Olivier Bonaventure
2019 J jnl
CoRR
François Michel, Quentin De Coninck, Olivier Bonaventure
2019 J jnl
Comput. Commun.
Fabien Duchene, David Lebrun, Olivier Bonaventure
2019 J jnl
CoRR
Olivier Bonaventure, Quentin De Coninck, Fabien Duchene, Mathieu Jadin, François Michel, Maxime Piraux, Chantal Poncin, Olivier Tilmans
2019 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2019 B conf
ICNP
Thomas Wirtgen, Cyril Dénos, Quentin De Coninck, Mathieu Jadin, Olivier Bonaventure
2019 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2019 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2019 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2018 J jnl
CoRR
François Michel, Quentin De Coninck, Olivier Bonaventure
2018 J jnl
Dagstuhl Reports
Vaibhav Bajpai, Olivier Bonaventure, Kimberly C. Claffy, Daniel Karrenberg
2018 conf
SIGCOMM Posters and Demos
Fabien Duchene, Mathieu Jadin, Olivier Bonaventure
2018 B conf
CNSM
Mathieu Xhonneux, Olivier Bonaventure
2018 J jnl
CoRR
Mathieu Xhonneux, Olivier Bonaventure
2018 J jnl
CoRR
Mathieu Xhonneux, Fabien Duchene, Olivier Bonaventure
2018 A conf
CoNEXT
Mathieu Xhonneux, Fabien Duchene, Olivier Bonaventure
2018 conf
SIGCOMM Posters and Demos
Quentin De Coninck, Olivier Bonaventure
2018 conf
EPIQ@CoNEXT
Maxime Piraux, Quentin De Coninck, Olivier Bonaventure
2018 J jnl
CoRR
Maxime Piraux, Quentin De Coninck, Olivier Bonaventure
2018 A conf
CoNEXT
François Aubry, Stefano Vissicchio, Olivier Bonaventure, Yves Deville
2018 B conf
Networking
Fabien Duchene, David Lebrun, Olivier Bonaventure
2018 conf
SOSR
David Lebrun, Mathieu Jadin, François Clad, Clarence Filsfils, Olivier Bonaventure
2018 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2018 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2018 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2018 B conf
Networking
Quentin De Coninck, Olivier Bonaventure
2018 conf
TMA
Viet-Hoang Tran, Hajime Tazaki, Quentin De Coninck, Olivier Bonaventure
2017 conf
ANRW
David Lebrun, Olivier Bonaventure
2017 B conf
ICNP
Fabien Duchene, Olivier Bonaventure
2017 A conf
CoNEXT
Quentin De Coninck, Olivier Bonaventure
2017 J jnl
IEEE/ACM Trans. Netw.
Stefano Vissicchio, Laurent Vanbever, Luca Cittadini, Geoffrey G. Xie, Olivier Bonaventure
2017 A* conf
INFOCOM
Mathieu Jadin, Gautier Tihon, Olivier Pereira, Olivier Bonaventure
2017 J jnl
CoRR
Gregory Vander Schueren, Quentin De Coninck, Olivier Bonaventure
2017 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2017 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2017 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2017 J jnl
Comput. Commun. Rev.
Olivier Bonaventure
2017 J jnl
RFC
Olivier Bonaventure, Christoph Paasch, Gregory Detal
2016 B conf
PAM
Quentin De Coninck, Matthieu Baerts, Benjamin Hesmans, Olivier Bonaventure
2016 conf
ANRW
Benjamin Hesmans, Olivier Bonaventure
2016 J jnl
RFC
Damien Saucez, Luigi Iannone, Olivier Bonaventure
2016 J jnl
Comput. Commun.
Viet-Hoang Tran, Quentin De Coninck, Benjamin Hesmans, Ramin Sadre, Olivier Bonaventure
2016 J jnl
IEEE Commun. Mag.
Quentin De Coninck, Matthieu Baerts, Benjamin Hesmans, Olivier Bonaventure
2016 A* conf
INFOCOM
Francois Aubry, David Lebrun, Stefano Vissicchio, Minh Thanh Khong, Yves Deville, Olivier Bonaventure
2015 A* conf
SIGCOMM
Renaud Hartert, Stefano Vissicchio, Pierre Schaus, Olivier Bonaventure, Clarence Filsfils, Thomas Telkamp, Pierre François
2015 conf
TMA
Benjamin Hesmans, Hoang Tran-Viet, Ramin Sadre, Olivier Bonaventure
2015 J jnl
RFC
Marcelo Bagnulo, Christoph Paasch, Fernando Gont, Olivier Bonaventure, Costin Raiciu
2015 conf
AIMS
Viet-Hoang Tran, Ramin Sadre, Olivier Bonaventure
2015 A* conf
INFOCOM
Stefano Vissicchio, Luca Cittadini, Olivier Bonaventure, Geoffrey G. Xie, Laurent Vanbever
2015 A* conf
MobiCom
Quentin De Coninck, Matthieu Baerts, Benjamin Hesmans, Olivier Bonaventure
2015 A conf
CoNEXT
Benjamin Hesmans, Gregory Detal, Sébastien Barré, R. Bauduin, Olivier Bonaventure
2015 A conf
CP
Renaud Hartert, Pierre Schaus, Stefano Vissicchio, Olivier Bonaventure
2015 ed.
TMA
Moritz Steiner, Pere Barlet-Ros, Olivier Bonaventure
2015 B conf
Networking
Francois Aubry, David Lebrun, Yves Deville, Olivier Bonaventure
2014 conf
CSWS@SIGCOMM
Christoph Paasch, Simone Ferlin, Ozgu Alay, Olivier Bonaventure
2014 J jnl
IEEE/ACM Trans. Netw.
François Clad, Pascal Mérindol, Jean-Jacques Pansiot, Pierre François, Olivier Bonaventure
2014 J jnl
Comput. Networks
Trong-Viet Ho, Yves Deville, Olivier Bonaventure
2014 J jnl
Commun. ACM
Christoph Paasch, Olivier Bonaventure
2014 J jnl
Comput. Commun. Rev.
Stefano Vissicchio, Laurent Vanbever, Olivier Bonaventure
2014 A* conf
INFOCOM
Stefano Vissicchio, Laurent Vanbever, Luca Cittadini, Geoffrey G. Xie, Olivier Bonaventure
2014 B conf
NOMS
David Lebrun, Stefano Vissicchio, Olivier Bonaventure
2014 A* conf
SIGCOMM
Benjamin Hesmans, Olivier Bonaventure
2014 B conf
Networking
Juan Antonio Cordero, Olivier Bonaventure
2013 conf
HotMiddlebox@CoNEXT
Benjamin Hesmans, Fabien Duchene, Christoph Paasch, Gregory Detal, Olivier Bonaventure
2013 J jnl
RFC
Mike Shand, Stewart Bryant, Stefano Previdi, Clarence Filsfils, Pierre François, Olivier Bonaventure
2013 J jnl
IEEE/ACM Trans. Netw.
Stefano Vissicchio, Laurent Vanbever, Cristel Pelsser, Luca Cittadini, Pierre François, Olivier Bonaventure
2013 J jnl
Comput. Commun. Rev.
Roch Guérin, Olivier Bonaventure
2013 J jnl
RFC
Luigi Iannone, Damien Saucez, Olivier Bonaventure
2013 conf
HotMiddlebox@CoNEXT
Gregory Detal, Christoph Paasch, Olivier Bonaventure
2013 A conf
CoNEXT
Christoph Paasch, Ramin Khalili, Olivier Bonaventure
2013 conf
REALWSN
Laurent Deru, Sébastien Dawans, Mathieu Ocaña, Bruno Quoitin, Olivier Bonaventure
2013 A conf
Internet Measurement Conference
Gregory Detal, Benjamin Hesmans, Olivier Bonaventure, Yves Vanaubel, Benoit Donnet
2013 J jnl
Comput. Networks
Gregory Detal, Christoph Paasch, Simon van der Linden, Pascal Mérindol, Gildas Avoine, Olivier Bonaventure
2013 J jnl
RFC
Alan Ford, Costin Raiciu, Mark Handley, Olivier Bonaventure
2013 A* conf
INFOCOM
Laurent Vanbever, Stefano Vissicchio, Luca Cittadini, Olivier Bonaventure
2012 ed.
Hot-ICE
Olivier Bonaventure, Ramana Rao Kompella
2012 B conf
Networking (1)
Damien Saucez, Juhoon Kim, Luigi Iannone, Olivier Bonaventure, Clarence Filsfils
2012 J jnl
login Usenix Mag.
Olivier Bonaventure, Mark Handley, Costin Raiciu
2012 J jnl
IEEE Internet Comput.
Damien Saucez, Luigi Iannone, Olivier Bonaventure, Dino Farinacci
2012 conf
CellNet@SIGCOMM
Christoph Paasch, Gregory Detal, Fabien Duchene, Costin Raiciu, Olivier Bonaventure
2012 Misc conf
NSDI
Costin Raiciu, Christoph Paasch, Sébastien Barré, Alan Ford, Michio Honda, Fabien Duchene, Olivier Bonaventure, Mark Handley
2012 J jnl
IEEE/ACM Trans. Netw.
Laurent Vanbever, Stefano Vissicchio, Cristel Pelsser, Pierre François, Olivier Bonaventure
2012 conf
LCN Workshops
Sébastien Dawans, Simon Duquennoy, Olivier Bonaventure
2012 A* conf
INFOCOM
Stefano Vissicchio, Luca Cittadini, Laurent Vanbever, Olivier Bonaventure
2011 J jnl
Comput. Networks
Pascal Mérindol, Pierre François, Olivier Bonaventure, Stéphane Cateloin, Jean-Jacques Pansiot
2011 J jnl
Comput. Commun.
Sébastien Barré, John Ronan, Olivier Bonaventure
2011 J jnl
Comput. Networks
Luigi Iannone, Damien Saucez, Olivier Bonaventure
2011 B conf
Networking (1)
Sébastien Barré, Christoph Paasch, Olivier Bonaventure
2011 A* conf
SIGCOMM
Damien Saucez, Olivier Bonaventure
2011 A* conf
SIGCOMM
Simon van der Linden, Gregory Detal, Olivier Bonaventure
2011 J jnl
Comput. Networks
Damien Leroy, Gregory Detal, Julien Cathalo, Mark Manulis, François Koeune, Olivier Bonaventure
2011 A* conf
SIGCOMM
Laurent Vanbever, Stefano Vissicchio, Cristel Pelsser, Pierre François, Olivier Bonaventure
2011 A conf
ITC
Ho Trong Viet, Yves Deville, Olivier Bonaventure, Pierre François
2010 J jnl
IEEE J. Sel. Areas Commun.
Virginie Van den Schrieck, Pierre François, Olivier Bonaventure
2010 conf
ServiceWave
Sébastien Barré, Olivier Bonaventure, Costin Raiciu, Mark Handley
2010 A* conf
SIGCOMM
Sébastien Barré, Olivier Bonaventure, Costin Raiciu, Mark Handley
2010 B conf
PAM
Jean-Jacques Pansiot, Pascal Mérindol, Benoit Donnet, Olivier Bonaventure
2010 J jnl
IEEE J. Sel. Areas Commun.
Loránd Jakab, Albert Cabellos-Aparicio, Florin Coras, Damien Saucez, Olivier Bonaventure
2010 A conf
Internet Measurement Conference
Pascal Mérindol, Benoit Donnet, Olivier Bonaventure, Jean-Jacques Pansiot
2010 A conf
ITC
Ho Trong Viet, Olivier Bonaventure, Yves Deville, Pham Quang Dung, Pierre François
2009 conf
PRESTO
Laurent Vanbever, Bruno Quoitin, Olivier Bonaventure
2009 conf
StudentWorkshop@CoNEXT
Gregory Detal, Damien Leroy, Olivier Bonaventure
2009 A conf
AsiaCCS
Mark Manulis, Damien Leroy, François Koeune, Olivier Bonaventure, Jean-Jacques Quisquater
2009 conf
U-NET@CoNEXT
Damien Leroy, Mark Manulis, Olivier Bonaventure
2009 A conf
ITC
Bruno Quoitin, Virginie Van den Schrieck, Pierre François, Olivier Bonaventure
2009 J jnl
IEEE Netw.
Olivier Bonaventure
2009 J jnl
IEEE Netw.
Olivier Bonaventure
2009 J jnl
IEEE Netw.
Olivier Bonaventure, Steve Uhlig, Mike H. MacGregor
2009 B conf
Networking
Damien Saucez, Benoit Donnet, Olivier Bonaventure
2009 J jnl
Int. J. Netw. Manag.
Damien Leroy, Olivier Bonaventure
2009 B conf
Networking
Virginie Van den Schrieck, Pierre François, Cristel Pelsser, Olivier Bonaventure
2009 A conf
Internet Measurement Conference
Pascal Mérindol, Virginie Van den Schrieck, Benoit Donnet, Olivier Bonaventure, Jean-Jacques Pansiot
2008 B conf
Networking
Damien Leroy, Olivier Bonaventure
2008 J jnl
IACR Cryptol. ePrint Arch.
Mark Manulis, Damien Leroy, François Koeune, Olivier Bonaventure, Jean-Jacques Quisquater
2008 J jnl
Comput. Commun. Rev.
Benoit Donnet, Olivier Bonaventure
2008 C conf
BROADNETS
Olivier Bonaventure
2008 J jnl
Comput. Commun. Rev.
Olivier Bonaventure, Augustin Chaintreau, Laurent Mathy, Philippe Owezarski
2008 J jnl
Int. J. Crit. Infrastructures
Nicolas Vanderavero, Xavier Brouckaert, Olivier Bonaventure, Baudouin Le Charlier
2008 J jnl
Int. J. Law Inf. Technol.
Romain Robert, Mark Manulis, Florence De Villenfagne, Damien Leroy, Julien Jost, François Koeune, Caroline Ker, Jean-Marc Dinant, Yves Poullet, Olivier Bonaventure, Jean-Jacques Quisquater
2007 conf
EUNICE
Damien Saucez, Benoit Donnet, Olivier Bonaventure
2007 A conf
CoNEXT
Damien Leroy, Olivier Bonaventure
2007 J jnl
IEEE/ACM Trans. Netw.
Olivier Bonaventure, Clarence Filsfils, Pierre François
2007 J jnl
IEEE Trans. Netw. Serv. Manag.
Pierre François, Olivier Bonaventure, Bruno Decraene, Pierre-Alain Coste
2007 J jnl
IEEE/ACM Trans. Netw.
Pierre François, Olivier Bonaventure
2007 A* conf
INFOCOM
Pierre François, Mike Shand, Olivier Bonaventure
2007 A conf
CoNEXT
Damien Saucez, Benoit Donnet, Olivier Bonaventure
2007 A conf
CoNEXT
Luigi Iannone, Olivier Bonaventure
2007 B ed.
PAM
Steve Uhlig, Konstantina Papagiannaki, Olivier Bonaventure
2006 J jnl
Comput. Networks
Cédric de Launois, Bruno Quoitin, Olivier Bonaventure
2006 B conf
Networking
Cristel Pelsser, Olivier Bonaventure
2005 J jnl
Int. J. Netw. Manag.
Bruno Quoitin, Cristel Pelsser, Olivier Bonaventure, Steve Uhlig
2005 A conf
CoNEXT
Olivier Bonaventure, Clarence Filsfils, Pierre François
2005 J jnl
Comput. Commun. Rev.
Pierre François, Clarence Filsfils, John Evans, Olivier Bonaventure
2005 A conf
CoNEXT
Pierre François, Olivier Bonaventure
2005 A* conf
INFOCOM
Pierre François, Olivier Bonaventure
2005 A conf
CoNEXT
Virginie Van den Schrieck, Olivier Bonaventure
2005 J jnl
IEEE Netw.
Olivier Bonaventure, Anja Feldmann, Lixin Gao, Timothy G. Griffin, Z. Morley Mao
2005 conf
QoS-IP
Cédric de Launois, Bruno Quoitin, Olivier Bonaventure
2005 J jnl
IEEE Netw.
Marcelo Yannuzzi, Xavier Masip-Bruin, Olivier Bonaventure
2005 B conf
NETWORKING
Cédric de Launois, Steve Uhlig, Olivier Bonaventure
2004 J jnl
Comput. Commun. Rev.
Steve Uhlig, Olivier Bonaventure
2004 Misc conf
SAC
Steve Uhlig, Olivier Bonaventure, Vincent Magnin, Chris Rapier, Luca Deri
2004 J jnl
Comput. Commun.
Bruno Quoitin, Sébastien Tandel, Steve Uhlig, Olivier Bonaventure
2004 J jnl
Comput. Commun.
David Hutchison, Laurent Mathy, Olivier Bonaventure
2004 J jnl
IEEE Netw.
Olivier Bonaventure
2004 conf
MIPS
Xavier Brouckaert, Olivier Bonaventure
2003 J jnl
IEEE Commun. Surv. Tutorials
Pierre Reinbold, Olivier Bonaventure
2003 J jnl
IEEE Commun. Mag.
Bruno Quoitin, Cristel Pelsser, L. Swinnen, Olivier Bonaventure, Steve Uhlig
2003 ch.
QofIS Final Report
Olivier Bonaventure, Panos Trimintzios, George Pavlou, Bruno Quoitin, Arturo Azcorra, Marcelo Bagnulo, Paris Flegkas, Alberto García-Martínez, Panos Georgatsos, Leonidas Georgiadis, Christian Jacquenet, L. Swinnen, Sébastien Tandel, Steve Uhlig
2003 J jnl
IEEE Netw.
Olivier Bonaventure
2003 book
Michael Smirnov, Ernst W. Biersack, Chris Blondia, Olivier Bonaventure, Olga Casals, Gunnar Karlsson, George Pavlou, Bruno Quoitin, James Roberts, Ioannis Stavrakakis, Burkhard Stiller, Panos Trimintzios, Piet Van Mieghem
2003 J jnl
IEEE Netw.
Olivier Bonaventure
2003 conf
QofIS
Cédric de Launois, Olivier Bonaventure, Marc Lobelle
2003 J jnl
IEEE Netw.
Olivier Bonaventure
2003 J jnl
Document Numérique
Stéphane Nicoll, Véronique Pirot, Olivier Bonaventure
2002 J jnl
Eur. Trans. Telecommun.
Steve Uhlig, Olivier Bonaventure
2002 conf
QofIS
Bruno Quoitin, Steve Uhlig, Olivier Bonaventure
2001 J jnl
IEEE Netw.
Olivier Bonaventure, Jordi Nelissen
2001 conf
QofIS
Steve Uhlig, Olivier Bonaventure
2000 J jnl
RFC
Olivier Bonaventure, Stefaan De Cnodder
2000 conf
QofIS
Steve Uhlig, Olivier Bonaventure
1999 J jnl
Comput. Commun. Rev.
Vincent Rosolen, Olivier Bonaventure, Guy Leduc
1999 J jnl
Formal Methods Syst. Des.
Guy Leduc, Olivier Bonaventure, Luc Léonard, Eckhart Koerner, Charles Pecheur
1996 J jnl
Comput. Commun.
Olivier Bonaventure, Espen Klovning, André A. S. Danthine
1996 J jnl
Eur. Trans. Telecommun.
Espen Klovning, Olivier Bonaventure
1996 conf
Protocols for High-Speed Networks
Olivier Bonaventure, Espen Klovning, André A. S. Danthine
1995 conf
High-Speed Networking for Multimedia Applications
André A. S. Danthine, Olivier Bonaventure
1995 conf
COST 237 Workshop
Espen Klovning, Olivier Bonaventure
1995 B conf
ICNP
Olivier Bonaventure, André A. S. Danthine, Espen Klovning, Olivier Danthine
1995 conf
COST 237 Workshop
Laurent Mathy, Olivier Bonaventure
1994 conf
Broadband Islands
Laurent Mathy, Guy Leduc, Olivier Bonaventure, André A. S. Danthine
1994 conf
COST 237 Workshop
Laurent Mathy, Olivier Bonaventure
1993 conf
Architecture and Protocols for High-Speed Networks
André A. S. Danthine, Olivier Bonaventure
redb/extractors/decompiler/DecompileBinja.py
← Index redb/extractors/decompiler/DecompileBinja.py python
import hashlib
import inspect
import json
import logging
import os
import signal
import time
from datetime import datetime, timezone
from typing import Dict, Any, Optional
from pathlib import Path
import subprocess
import sys

from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor
import magic
import pefile
from elftools.elf.elffile import ELFFile

# Import our BinjaDecompiler (conditional)
from redb.extractors.decompiler.bninja.decompiler import BinaryNinjaDecompiler

class DecompileBinja(Extractor):
    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
        filetype=None,
        decompile_modules=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious,
        )
        self.log.debug(inspect.currentframe().f_code.co_name)

        # Check if Binary Ninja is available
       # if not BINARYNINJA_AVAILABLE:
        #     self.log.error("Binary Ninja is not available in this container")
        #    raise ImportError(
        #        "Binary Ninja module not found - not available in feature extraction container"
        #    )
        self.analysis_results = None
        self.binja_decompiler = None
        self.filetype = filetype
        self.decompile_modules = decompile_modules or {"all"}
        self.goresym_data = None
        self.goresym_output_path = None

        # Convert TIMEOUT to integer with a default of 1200 seconds (20 minutes)
        try:
            self.BINJA_TIMEOUT = int(os.getenv("BINJA_TIMEOUT", "1200"))
        except ValueError:
            self.log.warning(
                "Invalid BINJA_TIMEOUT value, using default of 1200 seconds"
            )
            self.BINJA_TIMEOUT = 1200

        # Convert TIMEOUT to integer with a default of 1200 seconds (20 minutes)
        try:
            self.DECOMPILE_EXTRACTOR_TIMEOUT = int(
                os.getenv("DECOMPILE_EXTRACTOR_TIMEOUT", "2580")
            )
        except ValueError:
            self.log.warning(
                "Invalid DECOMPILE_EXTRACTOR_TIMEOUT value, using default of 2580 seconds"
            )
            self.DECOMPILE_EXTRACTOR_TIMEOUT = 2580

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup_run()

    def calculate_md5(self, input_str):
        """Calculate MD5 hash of a string."""
        return hashlib.md5(input_str.encode("utf-8")).hexdigest()

    def is_dotnet(self):
        """Check if the binary is a .NET assembly.

        Returns:
            bool: True if the file is a .NET assembly, False otherwise
        """
        try:
            if self.filetype == "pebin":
                file_type = magic.from_buffer(self.binary)
                if ".Net" in file_type:
                    return True
                pe = pefile.PE(self.filepath)
                for entry in pe.OPTIONAL_HEADER.DATA_DIRECTORY:
                    # IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR is typically 14
                    if (
                        entry.name == "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR"
                        and entry.Size > 0
                    ):
                        return True
                return False
            return False
        except AttributeError as e:
            self.log.error(
                f"AttributeError error dotnet file {self.hash.sha256} Full error : {e}"
            )
            return False

    def is_golang(self):
        """Check if the binary is a Go-compiled binary (heuristic).

        Supports PE and ELF binaries.
        """
        try:
            if self.filetype == "pebin":
                pe = pefile.PE(self.filepath)
                signatures = [b"Go build ID:", b"runtime.main", b"main.main"]

                for section in pe.sections:
                    data = section.get_data()
                    if any(sig in data for sig in signatures):
                        return True

                return False

            elif self.filetype == "elf":
                with open(self.filepath, "rb") as f:
                    elf = ELFFile(f)

                    # 1. Section-based checks
                    section_names = [sec.name for sec in elf.iter_sections()]
                    if any(
                        s in section_names
                        for s in (".note.go.buildid", ".gopclntab")
                    ):
                        return True

                    # 2. String scan in loadable sections
                    signatures = [
                        b"Go build ID:",
                        b"runtime.main",
                        b"runtime.goexit",
                        b"runtime.morestack",
                        b"main.main",
                    ]

                    for sec in elf.iter_sections():
                        if sec["sh_flags"] & 0x2:  # SHF_ALLOC
                            data = sec.data()
                            if any(sig in data for sig in signatures):
                                return True

                return False

            return False

        except Exception as e:
            self.log.error(
                f"Golang detection error {self.hash.sha256}: {e}"
            )
            return False

    def cleanup_run(self):
        """Clean up after analysis."""
        try:
            # BinaryNinjaDecompiler uses context manager pattern (__enter__/__exit__)
            # Cleanup happens automatically when exiting the 'with' block
            self.binja_decompiler = None

            # Clean up goresym temp file if it exists (keep in debug mode)
            if self.goresym_output_path and os.path.exists(self.goresym_output_path):
                if self.log.isEnabledFor(logging.DEBUG):
                    self.log.debug(f"Debug mode: keeping goresym output at {self.goresym_output_path}")
                else:
                    os.remove(self.goresym_output_path)
                    self.goresym_output_path = None

            # Force garbage collection
            import gc

            gc.collect()

        except Exception as e:
            self.log.error(f"Error in cleanup: {e}")

    def run_goresym(self, binary_path, output_json_path):
        """
            Run goresym on a Go binary and export its JSON output to a file.
            binary_path: path to the Go binary to analyze
            output_json_path: path where the JSON output will be saved
            """
        binary_path = str(Path(binary_path).resolve())
        output_json_path = str(Path(output_json_path).resolve())
        goresym_path = os.getenv("GORESYM_PATH", "GoReSym")

        try:
            # Example: goresym -t json /path/to/binary
            self.log.info("DEBUG: starting GoReSym")
            result = subprocess.run(
                [goresym_path, binary_path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
            )
        except FileNotFoundError:
            self.log.error("Error: 'goresym' not found in PATH. Make sure it is installed.")
            raise
        except subprocess.CalledProcessError as e:
            self.log.error("Error during goresym execution:")
            self.log.error(e.stderr)


        # Assuming goresym emits valid JSON to stdout.
        try:
            parsed = json.loads(result.stdout)
            # Store parsed JSON for later export to ClickHouse
            self.goresym_data = parsed
        except json.JSONDecodeError:
            # If it's not valid JSON, save the raw output instead.
            self.log.error("Warning: goresym output is not valid JSON; saving raw.")
            with open(output_json_path, "w", encoding="utf-8") as f:
                f.write(result.stdout)
            return

        # Save pretty-printed JSON for readability and debugging (used by BinaryNinja)
        with open(output_json_path, "w", encoding="utf-8") as f:
            json.dump(parsed, f, ensure_ascii=False, indent=2)
        self.goresym_output_path = output_json_path

        self.log.debug(f"goresym output saved to: {output_json_path}")

    def analyze_binary(self) -> Optional[Dict[str, Any]]:
        """Run Binary Ninja analysis and return results."""
        self.log.debug("Starting binary analysis")
        # if the binary is dotnet (only PE)
        if self.is_dotnet():
            self.log.debug("Skipping .NET binary - decompilation not supported")
            return None

        output_json_path = None
        ## if golang: run goresym
        try:
            if self.is_golang():
                output_json_path = "./goResym.json"
                self.run_goresym(self.filepath, output_json_path)
        except Exception as e:
            self.log.error(f"Error on GoReSym extraction: {e}")

        try:
            # Use BinaryNinjaDecompiler as a context manager to ensure proper setup/cleanup
            with BinaryNinjaDecompiler(
                filepath=self.filepath,
                timeout=self.BINJA_TIMEOUT,
                log=self.log,
                exporters=self.exporters,
                index_prefix=self.index_prefix,
                filetype=self.filetype,
                goresym=output_json_path,
                decompile_modules=self.decompile_modules,
            ) as decompiler:
                self.binja_decompiler = decompiler

                if decompiler.extract():
                    # Store results before context manager exits
                    results = decompiler.analysis_results
                    return results
                else:
                    self.log.error("BinaryNinjaDecompiler extraction failed")
                    return None

        except Exception as e:
            self.log.error(f"Error in Binary Ninja analysis: {e}")
            import traceback
            self.log.error(f"Traceback: {traceback.format_exc()}")
            return None

        finally:
            self.cleanup_run()

    def extract(self):
        """Extract and process all analysis results."""
        self.log.debug(inspect.currentframe().f_code.co_name)

        # Create a flag to track if extraction completed
        extraction_completed = False
        extraction_result = False
        extraction_error = None

        # Define the extraction process as a separate function
        def do_extraction():
            nonlocal extraction_completed, extraction_result, extraction_error
            try:
                results = self.analyze_binary()
                if not results:
                    extraction_result = False
                else:
                    self.analysis_results = results
                    # Add file hashes from parent Extractor class to analysis results
                    self.analysis_results["sha256"] = self.sha256
                    self.analysis_results["sha1"] = self.sha1
                    self.analysis_results["md5"] = self.md5
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        # Run extraction directly with signal-based timeout (no thread overhead).
        # SIGALRM is delivered by the OS, so there's no GIL contention or polling.
        old_handler = signal.getsignal(signal.SIGALRM)
        def _timeout_handler(signum, frame):
            raise TimeoutError("Extraction timed out")

        signal.signal(signal.SIGALRM, _timeout_handler)
        signal.alarm(self.DECOMPILE_EXTRACTOR_TIMEOUT)
        try:
            do_extraction()
        except TimeoutError:
            self.log.error(
                f"Extraction timed out after {self.DECOMPILE_EXTRACTOR_TIMEOUT} seconds"
            )
            self.cleanup_run()
            return None
        finally:
            signal.alarm(0)
            signal.signal(signal.SIGALRM, old_handler)

        if extraction_error:
            self.log.error(f"Error in extraction: {extraction_error}")
            return None

        # Return the actual analysis results, not just a boolean
        return self.analysis_results if extraction_result else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        """Prepare data for database export."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        if not self.analysis_results:
            return None

        # # Delegate to the BinjaDecompiler for consistent export formatting
        # if self.binja_decompiler:
        #     return self.binja_decompiler.prepare_export_data(exporter_type)
        # else:
        #     self.log.error("BinjaDecompiler not available for export preparation")
        #     return None

        if exporter_type == "ClickHouseExporter":
            now = datetime.now(timezone.utc)

            def prepare_array_field(value, array_type):
                """Helper to prepare array fields with proper null handling"""
                if value is None:
                    return []
                return value

            # Add a helper function to handle empty strings
            def ensure_not_empty(value, default="UNKNOWN"):
                """Ensure a string value is not empty"""
                if value is None or value == "":
                    return default
                return value

            def prepare_register_usage_map(register_dict):
                """Convert register usage dict to Map format with tuples
                Input: {"rbx": {"reads": 3, "writes": 1}, ...}
                Output: {"rbx": (3, 1), ...}
                """
                if not register_dict:
                    return {}
                return {
                    reg: (info.get("reads", 0), info.get("writes", 0))
                    for reg, info in register_dict.items()
                }


            decompile_modules = getattr(self, "decompile_modules", {"all"})
            run_all = "all" in decompile_modules
            run_decompilation = run_all or "decompilation" in decompile_modules
            run_disassembly = run_all or "disassembly" in decompile_modules
            run_llil = run_all or "llil" in decompile_modules
            run_cfg = run_all or "cfg" in decompile_modules
            run_strings = run_all or "strings" in decompile_modules

            export = {"multi_table": True}

            # Decompilation tables
            if run_decompilation:
                export["decompiled_content"] = {
                    "table": "code_binja_decompiled_functions_content",
                    "data": [
                        [
                            f["decompiled_function_hash"],
                            f["decompiled_function"],
                            f["function_type"],
                            f.get("flattened_score"),
                            f.get("mba_score"),
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "decompiled_function_hash",
                        "decompiled_function",
                        "function_type",
                        "flattened_score",
                        "mba_score",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "Nullable(Float64)",
                        "Nullable(Float64)",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["decompiled_refs"] = {
                    "table": "code_binja_decompiled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f["decompiled_function_hash"],
                            f.get("disassembled_function_hash"),
                            f["decompiled_function_name"],
                            f["decompiled_function_prototype"],
                            f["decompiled_function_address"],
                            prepare_array_field(f.get("functions_caller"), "Array(String)"),
                            prepare_array_field(f.get("functions_call"), "Array(String)"),
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "decompiled_function_hash",
                        "disassembled_function_hash",
                        "decompiled_function_name",
                        "decompiled_function_prototype",
                        "decompiled_function_address",
                        "functions_caller",
                        "functions_call",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "UInt64",
                        "Array(String)",
                        "Array(String)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Disassembly tables
            if run_disassembly:
                export["disassembled_content"] = {
                    "table": "code_binja_disassembled_functions_content",
                    "data": [
                        [
                            f["disassembled_function_hash"],
                            f.get("disassembled_function", ""),
                            f.get("disassembled_function_no_addresses", ""),
                            f.get("function_type", "UNKNOWN"),
                            f.get("instructions_count", 0),
                            prepare_array_field(
                                f.get("instructions_types"), "LowCardinality(String)"
                            ),
                            f.get("control_flow_count", 0),
                            prepare_array_field(
                                f.get("memory_access_pattern"), "LowCardinality(String)"
                            ),
                            prepare_array_field(
                                f.get("register_usage"), "LowCardinality(String)"
                            ),
                            f.get("data_references_count", 0),
                            f.get("max_block_size"),
                            f.get("num_calls"),
                            f.get("stack_size"),
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "disassembled_function",
                        "disassembled_function_no_addresses",
                        "function_type",
                        "instructions_count",
                        "instructions_types",
                        "control_flow_count",
                        "memory_access_pattern",
                        "register_usage",
                        "data_references_count",
                        "max_block_size",
                        "num_calls",
                        "stack_size",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Nullable(UInt32)",
                        "Nullable(UInt32)",
                        "Nullable(Int32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["disassembled_refs"] = {
                    "table": "code_binja_disassembled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f["disassembled_function_hash"],
                            f.get("decompiled_function_hash"),
                            f["disassembled_function_name"],
                            f["disassembled_function_address"],
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "disassembled_function_hash",
                        "decompiled_function_hash",
                        "disassembled_function_name",
                        "disassembled_function_address",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                # Function similarity metrics table (derived from disassembly data)
                # Lookup maps to join LLIL/MLIL features by disassembled_function_hash
                llil_by_hash = {
                    l.get("disassembled_function_hash"): l
                    for l in self.analysis_results.get("llil", [])
                    if l and l.get("disassembled_function_hash")
                }
                mlil_by_hash = {
                    m.get("disassembled_function_hash"): m
                    for m in self.analysis_results.get("mlil", [])
                    if m and m.get("disassembled_function_hash")
                }

                export["function_similarity_metrics"] = {
                    "table": "code_binja_function_similarity_metrics",
                    "data": [
                        [
                            f["disassembled_function_hash"],
                            f.get("cyclomatic_complexity"),
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            prepare_array_field(f.get("minhash"), "Array(UInt8)"),
                            (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_llil"),
                            (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get(
                                "tlsh_instruction_typed_llil"),
                            prepare_array_field(
                                (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_llil_skeleton"),
                                "Array(UInt8)",
                            ),
                            prepare_array_field(
                                (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_llil_typed"),
                                "Array(UInt8)",
                            ),
                            (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_mlil_skeleton"),
                            (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_mlil_typed"),
                            prepare_array_field(
                                (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_mlil_skeleton"),
                                "Array(UInt8)",
                            ),
                            prepare_array_field(
                                (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_mlil_typed"),
                                "Array(UInt8)",
                            ),
                            now,
                        ]
                        for f in self.analysis_results.get("disassembled", [])
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "cyclomatic_complexity",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "minhash",
                        "tlsh_llil_new",
                        "tlsh_instruction_typed_llil",
                        "minhash_llil_skeleton",
                        "minhash_llil_typed",
                        "tlsh_mlil_skeleton",
                        "tlsh_mlil_typed",
                        "minhash_mlil_skeleton",
                        "minhash_mlil_typed",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(UInt16)",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        # new
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(UInt8)",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(UInt8)",
                        "DateTime64(3, 'UTC')",
                    ],
                }


            # LLIL tables
            if run_llil:
                export["llil_content"] = {
                    "table": "code_binja_llil_functions_content",
                    "data": [
                        [
                            f["sha256_llil"],
                            f["function_type"],
                            prepare_array_field(
                                f.get("instructions_types_llil"), "LowCardinality(String)"
                            ),
                            f.get("control_flow_count_llil", 0),
                            prepare_array_field(
                                f.get("memory_access_pattern_llil"), "LowCardinality(String)"
                            ),
                            prepare_register_usage_map(f.get("register_usage", {})),
                            f.get("total_reg_reads", 0),
                            f.get("total_reg_written", 0),
                            f.get("data_references_count", 0),
                            f.get("max_block_size"),
                            f.get("num_calls"),
                            f.get("stack_size"),
                            prepare_array_field(f.get("body_llil_vector"), "Array(Tuple(UInt32, Array(UInt16)))"),
                            now,
                        ]
                        for f in self.analysis_results.get("llil", [])
                    ],
                    "column_names": [
                        "llil_function_hash",
                        "function_type",
                        "instructions_types_llil",
                        "control_flow_count_llil",
                        "memory_access_pattern_llil",
                        "register_usage_llil",
                        "total_reg_reads",
                        "total_reg_written",
                        "data_references_count",
                        "max_block_size",
                        "num_calls",
                        "stack_size",
                        "body_llil_vector",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "Map(LowCardinality(String), Tuple(UInt32, UInt32))",
                        "UInt32",
                        "UInt32",
                        "UInt32",
                        "Nullable(UInt32)",
                        "Nullable(UInt32)",
                        "Nullable(Int32)",
                        "Array(Tuple(UInt32, Array(UInt16)))",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["llil_refs"] = {
                    "table": "code_binja_llil_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f.get("sha256_llil"),
                            f.get("disassembled_function_hash"),
                            f.get("function_address"),
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            now,
                        ]
                        for f in self.analysis_results.get("llil", [])
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "llil_function_hash",
                        "disassembled_function_hash",
                        "function_address",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "Nullable(FixedString(64))",
                        "FixedString(64)",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Errors table (always include if per-function loop ran)
            if run_decompilation or run_disassembly or run_llil or run_cfg:
                export["function_analysis_errors"] = {
                    "table": "new_function_analysis_errors_binja",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["function_name"],
                            f["function_address"],
                            f.get("error_location", "unknown"),
                            f.get("error_message", ""),
                            f.get("error_details", ""),
                            f.get("error_type", "unknown"),
                            self.calculate_md5(
                                f"{f.get('error_message', '')}{f['function_name']}{f['function_address']}{f.get('error_location', 'unknown')}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results.get("errors", [])
                    ],
                    "column_names": [
                        "sha256",
                        "function_name",
                        "function_address",
                        "error_location",
                        "error_message",
                        "error_details",
                        "error_type",
                        "error_hash",
                        "status",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "UInt64",
                        "LowCardinality(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "FixedString(32)",
                        "Enum8('new'=1, 'investigating'=2, 'fixed'=3, 'wontfix'=4)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Strings table
            if run_strings:
                export["strings_raw"] = {
                    "table": "code_binja_strings_raw",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            s["string"],
                            s["string_raw"],
                            s["string_encoding"],
                            s["string_offset"],
                            s["string_length"],
                            s["string_raw_length"],
                            s["string_entropy"],
                        ]
                        for s in self.analysis_results.get("strings", [])
                    ],
                    "column_names": [
                        "sha256",
                        "string",
                        "string_raw",
                        "string_encoding",
                        "string_offset",
                        "string_length",
                        "string_raw_length",
                        "string_entropy",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "LowCardinality(String)",
                        "UInt64",
                        "UInt32",
                        "UInt32",
                        "Float32",
                    ],
                }

            # CFG function-level features table
            if run_cfg:
                export["cfg_functions"] = {
                    "table": "code_binja_cfg_functions",
                    "data": [
                        [
                            cfg.get("disassembled_function_hash"),
                            cfg["cfg_topology_hash"],
                            cfg["block_count"],
                            cfg["edge_count"],
                            cfg.get("llil_total_operations", 0),
                            cfg.get("call_count", 0),
                            cfg["cyclomatic_complexity"],
                            cfg.get("loop_count", 0),
                            cfg.get("max_depth", 0),
                            cfg.get("max_fan_out", 0),
                            cfg.get("md_index_topdown", 0),
                            cfg.get("md_index_bottomup", 0),
                            cfg.get("prime_product_llil", 0),
                            cfg.get("cfg_feature_tlsh"),
                            cfg.get("wl_minhash", []),
                            cfg.get("bb_features", []),
                            cfg.get("cfg_adjacency", []),
                            now,
                        ]
                        for cfg in self.analysis_results.get("cfg", [])
                        if cfg is not None
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "cfg_topology_hash",
                        "block_count",
                        "edge_count",
                        "llil_total_operations",
                        "call_count",
                        "cyclomatic_complexity",
                        "loop_count",
                        "max_depth",
                        "max_fan_out",
                        "md_index_topdown",
                        "md_index_bottomup",
                        "prime_product_llil",
                        "cfg_feature_tlsh",
                        "wl_minhash",
                        "bb_features",
                        "cfg_adjacency",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(16)",
                        "UInt16",
                        "UInt16",
                        "UInt32",
                        "UInt16",
                        "UInt16",
                        "UInt8",
                        "UInt16",
                        "UInt8",
                        "UInt64",
                        "UInt64",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(Array(UInt16))",
                        "Array(UInt32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # GoReSym metadata table (only if goresym data exists)
            if self.goresym_data:
                export["golang_metadata"] = {
                    "table": "redb_golang_metadata",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            json.dumps(self.goresym_data),
                            now,
                        ]
                    ],
                    "column_names": [
                        "sha256",
                        "goresym",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "JSON",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            return export

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.DECOMPILED.value

    def get_clickhouse_table(self) -> str:
        """Not used directly as we're handling multiple tables."""
        pass


if __name__ == "__main__":
    # Setup basic logging
    import logging
    import time

    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger("DecompileBinja")

    # Parse command line arguments
    import argparse

    parser = argparse.ArgumentParser(description="Binary Ninja Decompiler Wrapper")
    parser.add_argument("filepath", help="Path to the binary file to analyze")
    parser.add_argument(
        "--output", "-o", help="Output JSON file path (default: stdout)"
    )
    parser.add_argument(
        "--timeout",
        "-t",
        type=int,
        default=1200,
        help="Analysis timeout in seconds (default: 1200)",
    )
    args = parser.parse_args()
    start = time.perf_counter()
    # Create and run the extractor
    with DecompileBinja(args.filepath, logger) as extractor:
        success = extractor.extract()
        end = time.perf_counter()
        if not success:
            logger.error("Analysis failed")
            exit(1)

        # Output results
        if args.output:
            with open(args.output, "w") as f:
                json.dump(extractor.analysis_results, f)
            logger.info(f"Results written to {args.output}")
        else:
            print((extractor.analysis_results))
            with open("diff", "w") as f:
                f.write(str(f"{end - start:.3f} seconds"))